MySQL 5.7 中 innodb_buffer_pool_instances > 1 仅在 innodb_buffer_pool_size ≥ 1GB 时生效,否则自动降级为 1;其值建议设为 CPU 逻辑核数(≤64),且需满足 buffer_pool_size / instances ≥ 1MB;chunk 机制下各 instance 轮询分配 chunk,chunk_size 需为 1MB 整数倍且 ≤ 总大小 / 实例数;在线调整需先将 pool_size 设为 0 再重设,但推荐优雅重启以避免风险。

为什么 MySQL 5.7 的 innodb_buffer_pool_instances 设成大于 1 才有效?
因为 InnoDB 在 5.7 中强制要求:innodb_buffer_pool_size 必须 ≥ 1GB,innodb_buffer_pool_instances 才会被真正启用。如果 Buffer Pool 总大小小于 1GB,即使你设了 innodb_buffer_pool_instances = 8,MySQL 启动时会静默降级为 1,并在错误日志里写一句:[Warning] InnoDB: Using default value 1 for innodb_buffer_pool_instances.
这不是 bug,是源码硬编码的阈值(见 storage/innobase/srv/srv0start.cc)。所以调优前先确认:
-
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';—— 必须 ≥ 1073741824(即 1GB) -
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';—— 启动后必须返回你配置的值,不是 1
怎么选 innodb_buffer_pool_instances 的值?
它本质是把总 Buffer Pool 拆成 N 个独立锁保护的 chunk,目的是减少并发访问时的 latch 争用。值不是越大越好,关键看 CPU 核心数和实际负载模式:
- 常规建议:设为 CPU 核心数(逻辑核),但不超过 64;例如 16 核服务器,可试
innodb_buffer_pool_instances = 16 - 若
SHOW ENGINE INNODB STATUS\G中看到大量BUF_POOL_WAIT_FREE或log writes pending,说明 buffer pool 分片粒度太粗,可适当增加 - 但超过 32 后收益急剧下降,且每个 instance 至少要分到 1MB(否则初始化失败),所以
innodb_buffer_pool_size / innodb_buffer_pool_instances ≥ 1048576是硬约束
innodb_buffer_pool_instances 和 innodb_buffer_pool_chunk_size 的关系
5.7 引入了 chunk 机制——Buffer Pool 不再一次性分配大块内存,而是按 chunk(默认 128MB)动态扩展。而 innodb_buffer_pool_instances 决定了这些 chunk 如何在多个 instance 间轮询分配。
比如:innodb_buffer_pool_size = 4G,innodb_buffer_pool_instances = 4,innodb_buffer_pool_chunk_size = 128M → 总共 32 个 chunk,每个 instance 分到 8 个 chunk(即 1GB),各自管理自己的 page hash、LRU list、flush list。
注意:innodb_buffer_pool_chunk_size 不能随意改。它必须是 1MB 的整数倍,且不能超过 innodb_buffer_pool_size / innodb_buffer_pool_instances。否则启动报错:Invalid value for innodb_buffer_pool_chunk_size。
线上改配置会不会锁库?要不要重启?
MySQL 5.7 支持在线调整 innodb_buffer_pool_size 和 innodb_buffer_pool_instances,但有严格前提:
- 必须使用
SET GLOBAL且变量是动态的(5.7.5+ 支持) -
innodb_buffer_pool_instances只能在innodb_buffer_pool_size为 0 时修改(即先缩容到 0,再重设 size + instances) - 实际操作中,更稳妥的方式仍是配置文件修改 + 优雅重启:先
SET GLOBAL innodb_fast_shutdown = 0,再service mysql restart - 别信“完全不重启”的说法——resize 过程中会短暂阻塞 DML,且 instance 数量变更必然触发整个 buffer pool 重建,对高负载实例风险不小
真正容易被忽略的是:buffer pool resize 后,INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS 中的 POOL_ID 会重排,监控脚本如果硬编码了 instance ID,可能突然丢数据。



















