innodb_buffer_pool_size必须是innodb_buffer_pool_chunk_size与innodb_buffer_pool_instances乘积的整数倍,否则MySQL自动向下取整;默认chunk为128MB,若instances=8,则步进单位为1GB,设9G会变为8G。

innodb_buffer_pool_size 设置值必须是 chunk 的整数倍
MySQL 会强制校验 innodb_buffer_pool_size 是否满足 innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances 的整数倍关系。默认 innodb_buffer_pool_chunk_size 是 128MB,若你设了 innodb_buffer_pool_instances = 8,那最小合法单位就是 1GB(128MB × 8)。此时设 innodb_buffer_pool_size = 9G 会被自动向下取整为 8G —— 你查 SELECT @@innodb_buffer_pool_size 看到的就是 8G,不是 9G。
实操建议:
- 先确认当前
innodb_buffer_pool_instances和innodb_buffer_pool_chunk_size值(SHOW VARIABLES LIKE 'innodb_buffer_pool%') - 计算合法步进值:例如实例数=8、chunk=128MB → 步进=1024MB → 只能设 8G、9G、10G……不能设 8.5G
- MySQL 8.0+ 支持在线调整,但依然受 chunk 规则约束;5.7 必须重启生效
物理内存分配比例不是拍脑袋决定的
所谓“分配 70% 内存”是有前提的:服务器是否专用于 MySQL?有没有其他进程(如 Java 应用、Nginx、监控 agent)在争抢内存?盲目按 70% 设,可能触发系统 swap,反而拖垮性能。
更稳妥的做法:
- 用
free -h和vmstat 1观察空闲内存和 swap 使用率,预留至少 1.5~2GB 给 OS - 混合部署时,先估算其他服务常驻内存(如 Tomcat 堆 + 元空间 + native memory),再从剩余内存中按 50%~60% 分配给
innodb_buffer_pool_size - 专用 DB 服务器可上探至 80%,但需持续观察
Innodb_buffer_pool_wait_free状态变量 —— 非零说明缓冲池紧张,频繁等待空闲页
命中率低于 95% 不代表一定要调大 buffer pool
缓存命中率低,常见原因不一定是 buffer pool 小,而是查询模式问题。比如应用执行大量全表扫描、未走索引的 ORDER BY、或频繁访问冷数据,都会把热数据挤出 Young 区。
先排查再调参:
- 运行
SHOW ENGINE INNODB STATUS\G,看 “BUFFER POOL AND MEMORY” 段里的Database pages/Free buffers比例,若 free buffers 长期 > 10%,说明有冗余 - 检查慢查询日志,确认是否有缺失索引导致的扫描型 SQL
- 用
performance_schema查innodb_buffer_pool_read_requests和innodb_buffer_pool_reads计算真实命中率,公式:(1 - reads / read_requests) * 100
多实例(instances)不是越多越好
innodb_buffer_pool_instances 是为减少并发访问 buffer pool 时的 mutex 争用而设的,但它只在 buffer pool 总大小 ≥ 1GB 时才有效。设太高反而增加管理开销,且每个 instance 至少要分到 1GB 才有意义。
推荐组合:
- buffer pool ≤ 1GB:设为 1(默认)
- 1GB
- 8GB
- 32GB+:最多设 16,再高收益极小
注意:修改该参数必须重启 MySQL,且它会影响 chunk 校验逻辑 —— 改了 instances 就得重新核算 innodb_buffer_pool_size 是否合规。


















