MySQL 5.7在线调整innodb_buffer_pool_size后值不符,是因为实际大小必须为innodb_buffer_pool_chunk_size×innodb_buffer_pool_instances的整数倍,否则自动向上取整;例如设1228MB而粒度为1024MB时,实际生效2048MB,易致OOM。

MySQL 5.7 支持在线调整 innodb_buffer_pool_size,但不是“设多少就是多少”,实际生效值受 innodb_buffer_pool_chunk_size 和 innodb_buffer_pool_instances 严格约束,强行设置非整数倍值会被自动向上取整——这常导致内存意外超配、OOM。
为什么 SET GLOBAL innodb_buffer_pool_size 后查出来和你设的不一样
MySQL 5.7.5+ 把 buffer pool 拆成固定大小的 chunk 管理,每个 instance 包含相同数量的 chunk。最终实际大小必须满足:
-
innodb_buffer_pool_size = innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances × N(N 是正整数) -
innodb_buffer_pool_chunk_size默认是 128MB,不可动态修改;若未显式配置,MySQL 启动时会根据总 size 自动推导,但推导逻辑不稳定 - 例如:设
innodb_buffer_pool_size = 1228M,而默认chunk_size = 128M、instances = 8→ 最小单位是128 × 8 = 1024M,那么 1228M 会被自动上调到2 × 1024 = 2048M - 这种“悄悄变大”在小内存虚机(如 2G)上极易触发 OOM killer 杀掉 mysqld
如何安全执行在线调整
关键不是“能不能设”,而是“设完真按你想的走”。操作前必须确认三者关系:
- 先查当前值:
SHOW VARIABLES LIKE 'innodb_buffer_pool%'; - 算出理论最小粒度:
SELECT @@innodb_buffer_pool_chunk_size * @@innodb_buffer_pool_instances; - 你要设的目标值,必须是该粒度的整数倍;如果不是,手动向上取整(比如粒度是 1024M,目标 1500M → 改设为 2048M)
- 执行时用字节或带单位字符串均可:
SET GLOBAL innodb_buffer_pool_size = '2G';或SET GLOBAL innodb_buffer_pool_size = 2147483648; - 立即检查是否生效:
SELECT @@innodb_buffer_pool_size;,别只信命令返回“OK”
调整过程中会发生什么
这不是简单改个指针,而是后台线程 buf_resize_thread 在搬数据页,期间 buffer pool 会短暂不可用:
- 所有新请求可能被阻塞几十毫秒到数秒(取决于要移动的 page 数量)
- 可通过
SHOW STATUS LIKE 'Innodb_buffer_pool_resize_status';实时观察状态,常见值包括:Resizing buffer pool. Completed 123456789 / 234567890 pages. - 调整期间
information_schema.INNODB_BUFFER_POOL_STATS中的pages_data可能波动,属正常现象 - 不建议在高并发写入时段执行;如果 resize 卡住(status 长时间不动),需检查 error log 是否有内存分配失败记录
为什么 my.cnf 里写的值启动后又不准了
配置文件里的 innodb_buffer_pool_size 是“期望值”,MySQL 启动时仍会按 chunk 规则校准:
- 若你没配
innodb_buffer_pool_chunk_size,MySQL 会基于你写的 size 和默认instances(通常是 8)反推 chunk 大小,但这个反推值可能和运行时其他参数冲突 - 更稳妥的做法是:在 my.cnf 中**同时显式声明三者**,例如:
innodb_buffer_pool_size = 4G<br>innodb_buffer_pool_instances = 8<br>innodb_buffer_pool_chunk_size = 128M
- 这样启动时就能确定粒度为
128M × 8 = 1024M,4G 刚好是 4 倍,不会漂移 - 注意:
innodb_buffer_pool_chunk_size是只读参数,只能在配置文件中设,不能SET GLOBAL
真正麻烦的从来不是“怎么调”,而是“调完谁在用内存”。buffer pool 只占一部分,sort_buffer_size、join_buffer_size、连接数、performance_schema 都在抢内存。别光盯着 innodb_buffer_pool_size 看,free -h 和 ps aux --sort=-%mem 才是你该先打开的窗口。


















