MySQL MEMORY 引擎(舊稱 HEAP)將表數據完全存儲在內存中,提供極高的讀寫速度,適合臨時計算、查找表、會話存儲等場景。本文系統梳理其特性、限制、創建初始化、性能調優與避坑指南。
| 特性 | 說明 |
|---|---|
| 存儲介質 | 純內存(RAM),僅 .frm 結構文件落盤 |
| 數據持久性 | 重啟/崩潰數據全丟失,僅保留表結構 |
| 索引類型 | 支持 Hash(默認)與 B-Tree,Hash 僅支持 =/IN/<=> |
| 鎖粒度 | 表級鎖(Table Lock),並發寫入性能受限 |
| 行格式 | 固定長度(Fixed Row Format),VARCHAR 實際按 CHAR 存儲 |
| 不支持類型 | BLOB、TEXT、JSON、GEOMETRY |
| 最大表大小 | 受限於 max_heap_table_size(默認 16MB) |
| 並發特性 | 支持 INSERT DELAYED(讀優先),但表鎖仍為瓶頸 |
VARCHAR(255) 實際佔用 255 字符空間,嚴重浪費內存。對策:短字符串用 CHAR,長字符串避免用 MEMORY,改用 InnoDB + Buffer Pool 預熱。max_heap_table_size 限制總大小,超限報錯 The table 'tbl' is full。CREATE TABLE `session_cache` (
`session_id` CHAR(32) NOT NULL,
`user_id` INT UNSIGNED NOT NULL,
`data` VARBINARY(1024) NOT NULL, -- 固定長度二進制,避免 VARCHAR 浪費
`expire_at` INT UNSIGNED NOT NULL,
PRIMARY KEY (`session_id`),
INDEX `idx_expire` (`expire_at`) USING BTREE -- 範圍清理需 B-Tree
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4;
[mysqld]
# 最大內存表大小(單位字節),根據業務評估調大,如 256MB
max_heap_table_size = 268435456
tmp_table_size = 268435456 # 內部臨時表同步調大
/opt/mysql/init_memory_tables.sql,包含所有 MEMORY 表的 INSERT 或 LOAD DATA 語句。my.cnf:[mysqld]
init-file = /opt/mysql/init_memory_tables.sql
要求:腳本每行一條完整語句,無註釋,執行順序滿足依賴關係。
應用啟動時檢查表行數,為空則批量寫入基礎數據(字典表、配置表、權限表)。優點:邏輯集中、易維護、支持多實例。
從持久表同步至 MEMORY 表,增加寫入延遲與複雜度。
| 場景 | 適用性 | 替代方案 |
|---|---|---|
| 系統配置/字典表(極少變更、高頻讀) | ✅ 極佳 | Redis、本地緩存 |
| 會話存儲(Session) | ⚠️ 可用,但表鎖限制並發 | Redis Cluster(推薦) |
| 臨時計算中間表(ETL、報表) | ✅ 極佳 | InnoDB 臨時表、CTE |
| IP 地址庫/郵編查找表 | ✅ 極佳 | Redis、Memory Mapped File |
| 高並發寫入日誌/計數器 | ❌ 不適合 | InnoDB + Change Buffer、Redis |
| 大文本/JSON 存儲 | ❌ 不支持 | InnoDB、MongoDB |
USING BTREE。SHOW TABLE STATUS LIKE 'tbl\G 關注 Data_length、Max_data_length;SHOW GLOBAL STATUS LIKE 'Created_tmp_tables' 觀察內部臨時表是否轉磁碟。max_heap_table_size 導致寫入報滿。