myisam和innodb内存占用不可直接对比rss:myisam依赖os page cache导致rss虚低,innodb将热数据缓存在buffer pool中rss真实高;必须叠加两者评估总内存占用,且innodb需合理配置innodb_buffer_pool_size(50%–75%物理内存)、调低key_buffer_size、禁用无效缓存。

只看ps aux的RSS会严重误判
mysqld进程的RSS值对MyISAM和InnoDB完全不具可比性。MyISAM把表数据全扔给OS page cache,mysqld进程自身RSS低,但/proc/[pid]/maps里mapped file区域可能吃掉十几GB;InnoDB则把热数据页全塞进innodb_buffer_pool_size,RSS高得真实。你看到MyISAM“省内存”,其实是把账记到了OS头上。
实操建议:
- 查InnoDB真实缓冲池使用率:运行SHOW ENGINE INNODB STATUS\G,找Buffer pool size和Free buffers,算出已用比例
- 查MyISAM索引缓存实际占用:SHOW STATUS LIKE 'Key_blocks_used' × key_cache_block_size
- 同时用cat /proc/$(pgrep mysqld)/maps | awk '$6 ~ /\[.*\]/ {sum += $2} END {print sum/1024/1024 " MB"}'看OS层mapped file总量
- 对比时必须两者叠加,否则结论无效
innodb_buffer_pool_size设小是最大陷阱
迁移后QPS暴跌、慢查询激增,90%以上是因为innodb_buffer_pool_size还沿用MyISAM时代的配置(比如128M或256M)。MyISAM靠key_buffer_size缓索引,数据靠OS读;InnoDB没缓冲池就等于裸盘扫描。
实操建议:
- Linux下设为物理内存的50%–75%,但必须预留至少2GB给OS和其他进程(尤其开了tmp_table_size或sort_buffer_size时)
- 检查是否被innodb_dedicated_server=ON干扰:运行SHOW VARIABLES LIKE 'innodb_dedicated_server',混部环境务必关掉
- 确保值是innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances的整数倍(默认128MB × 8 = 1024MB),否则启动时自动向下取整
- 改完重启,立刻查Buffer pool hit rate,持续低于99.5%就得再调大
key_buffer_size不降会抢内存
MyISAM时代设的key_buffer_size(比如256M)在InnoDB为主力后毫无意义,反而和缓冲池争抢物理内存,触发swap或OOM。这不是“留着也无害”,而是明确的资源浪费。
实操建议:
- 迁移完成后立即将key_buffer_size从256M降到32M甚至8M
- 若库中仍有少量MyISAM表,按实际索引大小估算:SELECT SUM(index_length) FROM information_schema.tables WHERE engine='MyISAM',设为该值的1.2倍即可
- 别忽略query_cache_size(MySQL 8.0+已废弃),旧配置残留会白占内存
别信“小表不用调”这种说法
哪怕单表只有500MB,只要它频繁参与JOIN、范围扫描或ORDER BY,innodb_buffer_pool_size太小照样导致大量随机IO。InnoDB的缓存单位是页(16KB),不是整张表——热点页分散在不同表之间,缓冲池必须够大才能留住它们。
容易被忽略的点:
- innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup默认开启,重启后前几分钟QPS可能腰斩,生产环境建议关掉
- SSD机器上MyISAM的“省内存”优势基本消失,反而因缺乏预读和合并写入,I/O效率更低
- innodb_adaptive_hash_index在读多写少场景有用,但高并发更新下可能引发latch竞争,SHOW ENGINE INNODB STATUS里若见大量hash search latch waits就得关掉











