MySQL 8.0升级后内存明显增加主因是innodb_buffer_pool_size自动推导行为突变(如chunk_size动态计算导致向上对齐)叠加performance_schema全开预分配300–500MB;显式配置chunk_size、调整instances并关闭非必要P_S consumer可解决90%以上RSS异常增长。

MySQL 8.0 升级后内存“明显增加”,90%以上不是 bug,而是 innodb_buffer_pool_size 自动推导行为突变 + performance_schema 全开预分配导致的——调这两个参数,能解决绝大多数 RSS 异常增长问题。
为什么 innodb_buffer_pool_size 显示值和实际 RSS 差一倍?
MySQL 8.0.22+ 默认启用自动计算 innodb_buffer_pool_chunk_size,若你没显式设置它,MySQL 会按物理内存动态算 chunk(比如 64GB 机器默认算出 256MB),再乘以 innodb_buffer_pool_instances(默认 8),最终分配内存 = chunk × instances × 实际 chunk 数量。而你配置的 innodb_buffer_pool_size 只是“目标值”,InnoDB 会向上对齐到合法倍数。
常见表现:
-
SHOW VARIABLES LIKE 'innodb_buffer_pool_size'返回 40GB,但SHOW ENGINE INNODB STATUS\G里 “Buffer pool size” 显示 5242880 × 16KB ≈ 80GB - 启动日志出现 warning:
"Buffer pool size rounded up to ..." -
SELECT @@innodb_buffer_pool_chunk_size, @@innodb_buffer_pool_instances, @@innodb_buffer_pool_size发现三者无法整除
实操建议:
- 在
/etc/my.cnf的[mysqld]段显式写死:innodb_buffer_pool_chunk_size = 128M(必须是 1M 整数倍) - 同步设
innodb_buffer_pool_instances,确保innodb_buffer_pool_size / (128 * 1024 * 1024 * innodb_buffer_pool_instances)是整数(例如 buffer_pool 设为 2G,instances 就选 2、4 或 8) - 删掉旧的
ib_logfile0和ib_logfile1(路径通常为/www/server/data/或/var/lib/mysql/),否则启动报错
为什么 performance_schema 一开就多占 300–500MB?
MySQL 8.0 默认全量启用所有 instruments 和 consumers,其中 events_statements_history_long 和 events_transactions_history_long 这类长历史表,单个默认预分配 128MB+ 内存——启动即占,不查也吃。
实操建议:
- 确认是否真被它吃掉:运行
SELECT * FROM performance_schema.memory_summary_global_by_event_name WHERE event_name LIKE 'memory/performance_schema/%' ORDER BY SUM_ALLOCATED DESC LIMIT 10 - 关掉非调试用 consumer:
UPDATE performance_schema.setup_consumers SET ENABLED = 'NO' WHERE NAME IN ('events_statements_history_long', 'events_transactions_history_long') - 限制历史表大小(写入 my.cnf):
performance_schema_events_statements_history_long_size = 10000(默认 20000),同理设performance_schema_events_transactions_history_long_size = 10000 - 禁用非核心 instruments(运行时生效):
UPDATE performance_schema.setup_instruments SET ENABLED = 'NO' WHERE NAME LIKE 'statement/sql/%' AND NAME NOT IN ('statement/sql/select','statement/sql/insert','statement/sql/update','statement/sql/delete')
为什么改了配置但内存没降?
最常见原因是 MySQL 根本没读你改的配置文件。MySQL 8.0 启动时只认固定路径:/etc/my.cnf → /etc/mysql/my.cnf → /usr/etc/my.cnf → ~/.my.cnf。/www/server/mysql/my.cnf 不在默认列表里,除非显式加 --defaults-file 参数。
实操建议:
- 确认实际加载路径:
ps aux | grep mysqld | grep -o '\-\-defaults-file=[^ ]*';若无输出,说明走默认路径 - 最稳妥做法:删掉或重命名
/etc/my.cnf,然后确保/www/server/mysql/my.cnf顶部有[mysqld]段落,并把innodb_buffer_pool_chunk_size、performance_schema_*等参数放进去 - 改完重启前先验证:
mysqld --defaults-file=/www/server/mysql/my.cnf --verbose --help | grep "buffer_pool_size"
容易被忽略的隐性内存放大点
除了 buffer pool 和 P_S,还有几个点会在升级后突然暴露出来:
-
innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup默认均为 ON,启动时会快速加载上次 dump 的热页(ib_buffer_pool文件),表现为几秒内 RSS 陡增——这不是泄漏,但容易误判;可设SET GLOBAL innodb_buffer_pool_load_at_startup = OFF关闭 - 线程级缓冲区(
sort_buffer_size、join_buffer_size)默认值虽小,但连接数一多就雪崩;检查max_connections是否远高于真实并发,避免为闲置连接预分配内存 - 升级后若仍保留
query_cache_type = 1(5.7 常见),MySQL 8.0 已移除 query cache,该配置会被忽略,但部分旧脚本可能残留并引发元数据缓存异常
真正关键的不是“总内存多少”,而是 innodb_buffer_pool_pages_free 是否长期低于 5%,以及 Buffer pool hit rate 是否持续低于 99.5%——这些指标比 RSS 数值更能反映配置是否合理。


















