myisam内存开销仅限key_buffer_size索引缓存,表数据依赖os文件缓存,造成rss低但系统page cache压力大;innodb需缓冲池同时缓存数据与索引页,并承担undo/redo、锁、mvcc等事务开销,内存占用高但保障一致性与并发安全。

MyISAM 的内存开销只集中在 key_buffer_size
MyISAM 几乎不管理数据页缓存,key_buffer_size 是它唯一主动分配的内存区域,只用来缓存索引块(.MYI 文件)。表数据(.MYD)完全绕过 MySQL 内存管理,由操作系统负责文件缓存——这意味着 MySQL 进程自身 RSS 很低,看起来“很轻”。
常见错误现象:SHOW STATUS LIKE 'Key%' 显示 Key_reads 飙高但 Key_read_requests 不高,说明索引块频繁换入换出;ps aux 看 mysqld RSS 占用低,但 /proc/[pid]/status 或 cat /proc/[pid]/maps | grep -i "cache" 会发现大量 page cache 被占用,影响其他服务。
InnoDB 缓冲池必须同时缓存数据和索引页
InnoDB 的内存压力主要来自 innodb_buffer_pool_size,它默认同时缓存数据页和索引页(聚簇+辅助索引),且每页固定 16KB。即使一个空表或小表,只要被访问过,也会在缓冲池中占至少一页空间;海量小表会快速摊薄缓冲池利用率,导致大量冷页竞争淘汰。
-
innodb_buffer_pool_instances分片数设得太小(如默认 1),会导致热点页锁争用,进一步降低有效缓存率 - 开启
innodb_file_per_table=ON后,每个小表对应一个 .ibd 文件,但缓冲池仍需为每个表维护元数据、自适应哈希索引、change buffer 等结构,开销不可忽略 - 如果启用
innodb_adaptive_hash_index,每个表的热点查询路径都会生成哈希条目,小表多时易引发 latch 竞争
OS 层缓存行为差异放大“省内存”假象
MyISAM 的 .MYD 文件是纯堆组织,顺序读写友好,OS page cache 能高效复用;而 InnoDB 的聚簇索引 + MVCC 版本链导致随机访问更密集,page cache 命中率天然偏低。尤其在 SSD + 大内存机器上,MyISAM 的“省内存”优势其实是把缓存压力转移给了 OS,且无法控制粒度——你看到的低 RSS,掩盖了真实的系统级内存争用。
实操建议:
- 监控不能只看
ps aux的 RSS,要结合SHOW ENGINE INNODB STATUS中的Buffer pool size和Free buffers,再算已用比例 - 对 MyISAM,用
Key_blocks_used * key_cache_block_size估算实际索引缓存用量,并检查/proc/sys/vm/vfs_cache_pressure是否被压得过高 - 若真有海量小表且读多写少,可考虑合并小表(如按业务维度归档为分区表),而非硬切 MyISAM
别忘了崩溃恢复和事务成本是隐性内存消耗
MyISAM 没有 undo log、redo log、MVCC 版本链,也不维护事务状态,所以进程内无这部分内存开销;InnoDB 却必须为每个活跃事务保留 undo 日志指针、锁结构、插入缓冲区等。即使小表没写操作,只要连接存在、事务未显式结束,这些结构就一直驻留。
容易被忽略的一点:MyISAM 的“省”是有代价的——它不支持行锁、崩溃后可能丢数据、无法热备、长查询会锁整表。2026 年的生产环境里,用 MyISAM 换取那点内存节省,往往换来的是更难诊断的抖动和更高的运维风险。











