结论是:设大不一定快,设错反而拖垮整个系统;真正起效的配置必须同时满足“命中率够高 + 内存不抢资源 + chunk 对齐”三个硬条件。

直接说结论:设大不一定快,设错反而拖垮整个系统;真正起效的配置必须同时满足“命中率够高 + 内存不抢资源 + chunk 对齐”三个硬条件。
怎么看当前缓冲池是不是真够用
别信内存占用率,看真实命中率。执行 SHOW ENGINE INNODB STATUS\G,找到 BUFFER POOL AND MEMORY 部分,用这个公式算:
命中率 = (1 − innodb_buffer_pool_reads / innodb_buffer_pool_read_requests) × 100%
- 低于 95%:磁盘读太多,大概率要调大
- 高于 99.5%:再加收益极低,还可能挤占系统内存,引发
si/so非零(vmstat 1可查) - 同时盯住
innodb_buffer_pool_pages_free是否长期为 0,以及innodb_buffer_pool_wait_free是否大于 0 —— 后者一出现,说明线程在等空闲页,必须扩容或砍掉全表扫描
设多大才安全又有效
不是按比例拍脑袋,而是按物理内存分档+留余量:
- ≤ 4G 内存:设
innodb_buffer_pool_size = 2g(50%,再高容易触发 swap) - 8G 内存:选
5g~6g,优先5g(避开临界抖动) - 16G 内存:设
10g或12g,跳过11g(非 128M chunk 对齐) - 32G+ 内存:上限卡在 80%,但必须满足
innodb_buffer_pool_size是innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances的整数倍
例如 32G 服务器,innodb_buffer_pool_chunk_size 默认 128M,若设 innodb_buffer_pool_instances = 16,则合法值只能是 128M × 16 × N → 24G(192 × 128M)是合法的,24g 才生效;写成 24g 但没配 instances,MySQL 会自动向下取整到最近合法值,你根本不知道自己没设成功。
动态调大时最容易栽的三个坑
MySQL 5.7+ 支持在线调大,但以下情况会让操作失效或埋雷:
- 新值不是 chunk 对齐倍数 → MySQL 静默取整,
SELECT @@innodb_buffer_pool_size查到的和你 SET 的不一致 - 只调
innodb_buffer_pool_size,没同步调innodb_buffer_pool_instances→ 实例太少,高并发下Mutex spin waits暴涨(SHOW ENGINE INNODB STATUS里看) - 调完不盯
free -h和vmstat 1→ 出现si或so> 0,说明系统开始 swap,响应速度会断崖下跌
配套必须开的两个开关
光调大小不够,重启后缓存清空,前几分钟性能会暴跌。必须补上:
-
innodb_buffer_pool_dump_at_shutdown = ON:关机时把热页地址存到磁盘 -
innodb_buffer_pool_load_at_startup = ON:启动时自动加载,几秒内恢复热点
这两个参数默认关闭,不手动开等于白调。注意 dump 文件路径由 innodb_buffer_pool_filename 控制,默认在数据目录下,确保磁盘有空间且权限可读写。











