MySQL 8.0升级后内存“暴涨”主因是innodb_buffer_pool_size默认按物理内存自动计算(如64GB机器分48GB),而5.7及以前用保守固定值(8MB–128MB),叠加performance_schema全开占用300–500MB;需显式配置buffer pool大小与chunk_size、关闭非必要P_S consumer并协同调优max_connections等参数。

innodb_buffer_pool_size 默认行为变了,不是 bug,是配置逻辑升级导致的。
为什么 SHOW VARIABLES 显示的 innodb_buffer_pool_size 和实际 RSS 差一大截
MySQL 8.0+ 启动时会自动按物理内存推算 innodb_buffer_pool_size(公式类似 min(总内存 × 0.75, 12G)),而 5.7 及以前版本默认只给 8MB–128MB。一台 64GB 机器在 8.0 下可能直接分走 48GB,但 SHOW VARIABLES 只显示你“写进配置的值”,不反映实际对齐后的分配量。
真实分配由 innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances × chunk 数量决定,且必须向上对齐。常见表现:
-
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结果无法整除
为什么 performance_schema 一开就多占 300–500MB
MySQL 8.0 默认全量启用 performance_schema 的 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') - 限制大小(写入
/etc/my.cnf):performance_schema_events_statements_history_long_size = 10000 - 确认 MySQL 真读的是哪个配置文件——宝塔用户常改
/www/server/mysql/my.cnf,但 MySQL 默认只认/etc/my.cnf,否则参数不生效
为什么重启后内存瞬间飙高,甚至被 OOM Killer 杀掉
MySQL 8.0 默认开启 innodb_buffer_pool_dump_at_shutdown 和 innodb_buffer_pool_load_at_startup。dump 文件本身不大,但加载时会批量预热页面,造成几秒内 RSS 峰值陡增——尤其 buffer pool > 4G 或 SSD 较慢时极易触发 OOM。
检查方式:
-
SHOW VARIABLES LIKE 'innodb_buffer_pool_dump_at_shutdown'和innodb_buffer_pool_load_at_startup,两者默认均为 ON - 临时禁用:
SET GLOBAL innodb_buffer_pool_load_at_startup = OFF - 长期方案:配置文件中写死
innodb_buffer_pool_load_at_startup = OFF,或删掉旧ib_buffer_pool文件(路径通常为/www/server/data/或/var/lib/mysql/)
为什么调小 innodb_buffer_pool_size 却没生效
在线执行 SET GLOBAL innodb_buffer_pool_size = 2*1024*1024*1024 失败,常见卡点:
- 新值不是
innodb_buffer_pool_chunk_size×innodb_buffer_pool_instances的整数倍(默认 chunk 是 128MB,所以 2G 合法,1.5G 就非法,会被向下取整) - 没同步设
innodb_buffer_pool_chunk_size,导致 MySQL 自动推导出一个不匹配的 chunk 大小 - 配置文件路径错误,或未重启服务,或重启时语法校验失败(建议先运行
mysqld --defaults-file=/etc/my.cnf --verbose --help 2>/dev/null | head -5) - 启用了
innodb_dedicated_server = ON(8.0 默认开启),它会无视你的配置,按物理内存自动设值;必须显式设为OFF
真正要压住内存,得同时锁死 innodb_buffer_pool_size、innodb_buffer_pool_chunk_size、innodb_buffer_pool_instances 三者关系,并关掉 performance_schema 长历史表和 buffer pool 预热——少动一个,就可能白调。


















