必须同步配置innodb_buffer_pool_chunk_size和innodb_buffer_pool_instances,否则innodb_buffer_pool_size会被自动向上取整为chunk_size×instances的整数倍,导致内存浪费或OOM;例如设1228M但实际生效2048M,因默认chunk=128M、instances=8,最小粒度1024M,1228M非其整数倍而被升至2×1024M。

不能只调 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 是正整数)
常见错误现象:
- my.cnf 写了
innodb_buffer_pool_size = 1228M,但SELECT @@innodb_buffer_pool_size返回2147483648(即 2048MB) - 在 2G 虚机上设 1228MB,结果 buffer pool 占满内存,
mysqld被 OOM killer 杀掉
原因:默认 innodb_buffer_pool_chunk_size = 128M,innodb_buffer_pool_instances = 8 → 最小粒度是 128 × 8 = 1024M,1228M 不是整数倍,系统自动按 2×1024M = 2048M 生效。
怎么安全执行在线调整
关键不是“能不能设”,而是“设完真按你想的走”。操作前必须确认三者关系:
- 先查当前值:
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的统计可能滞后或不一致
吞吐量提升的关键配比逻辑
单纯增大 innodb_buffer_pool_size 并不保证吞吐上升,需配合实例与 chunk 分布:
- 若
innodb_buffer_pool_size > 1G,innodb_buffer_pool_instances建议设为 CPU 逻辑核数(如 4 核 → 设 4),避免多线程争抢同一 buffer pool 锁 -
innodb_buffer_pool_chunk_size默认 128MB,不可动态修改;若你设了非默认值(如 256MB),必须确保它 ≤innodb_buffer_pool_size / innodb_buffer_pool_instances - 生产环境推荐缓冲池占总内存的 50%–75%,但必须满足:目标值 ÷(chunk_size × instances) = 整数
- 例如:16GB 内存服务器,想配 12GB buffer pool,选 instances=8,则 chunk_size 必须是 12GB ÷ 8 = 1.5GB → 不合法(chunk_size 最大支持 128MB × 1000 = 128GB,但最小单位仍是 1MB,且受实例数限制);更稳妥做法是固定 chunk_size=128MB,instances=8 → 最小粒度 1024MB → 只能设 10GB、11GB…12GB 不行,得设 12288MB(12GB)?错,12288 ÷ 1024 = 12 → 可以,因为 1024 × 12 = 12288
真正容易被忽略的是:每次在线调整建议增幅不超过 20%,避免 resize 时间过长导致业务抖动;而 my.cnf 中的静态配置仍需同步更新,否则重启后失效。











