innodb_buffer_pool_size并非越大越好,需预留足够内存给OS和其他进程,避免触发Swap;建议上限为available内存的70%且不超物理内存60%,NUMA架构下须按单节点内存合理分配。

innodb_buffer_pool_size设多大才不触发Swap
这个值不是越大越好,也不是按物理内存百分比硬套。它必须留出足够空间给OS、其他进程、以及内核页表等开销。常见错误是设到70%甚至80%,结果OS只剩不到2GB可用内存,直接触发kswapd回收匿名页(即MySQL的Buffer Pool页),开始swap out。
关键看free -g输出里的available列,不是free列。如果available持续低于4GB,Buffer Pool再大也白搭。
- 生产环境建议:Buffer Pool上限 =
available× 0.7,且不超过物理内存的60% - 若服务器有2个NUMA node,每个node有64GB本地内存,则
innodb_buffer_pool_size应设为40GB左右,而不是80GB——后者会让内核跨node分配,引发numa_miss和换页风暴 - 验证是否生效:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';和SHOW ENGINE INNODB STATUS\G中的Buffer pool size字段必须一致
为什么开了O_DIRECT还在Swap
innodb_flush_method=O_DIRECT只影响InnoDB数据文件的读写路径(绕过page cache),但它完全不控制Buffer Pool本身的内存驻留行为。Buffer Pool分配的是匿名页(anon page),而Linux对匿名页的回收策略就是swap——哪怕你禁了page cache,只要内核判定内存压力大,照样把Buffer Pool页swap出去。
所以关swap或调低vm.swappiness只是治标;真正要盯的是Buffer Pool是否被系统“误判”为可换出内存。
-
vm.swappiness必须设为0(不是10),否则即使有空闲内存,内核仍可能主动换出anon页 - 用
numastat -p $(pgrep mysqld)检查各node的Heap分布,若numa_hitO_DIRECT再怎么配也没用 - MySQL 5.6.27+ 可直接在
my.cnf中加innodb_numa_interleave = ON,比shell层numactl更可靠
Buffer Pool配置与NUMA绑定不生效的典型表现
明明写了innodb_buffer_pool_size,也加了numactl --interleave all,但vmstat里si/so还是跳,numastat显示numa_miss高、heap集中在单node——说明配置没落地。
- systemd服务中启动命令未覆盖
ExecStart,导致numactl没生效;正确做法是修改/usr/lib/systemd/system/mysqld.service,把原ExecStart替换成ExecStart=/usr/bin/numactl --interleave=all /usr/sbin/mysqld $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION - Docker容器内用
numactl需加--cap-add=SYS_ADMIN,否则报Operation not permitted -
innodb_numa_interleave = ON仅在MySQL启动时读取一次,运行中SET GLOBAL无效
监控和验证Swap抖动是否真由Buffer Pool引起
不能只看vmstat的si/so,得确认是不是Buffer Pool页被换出。因为Swap也可能来自临时表、排序缓冲区或应用层泄漏。
- 查
/proc/zoneinfo中各node的nr_inactive_anon与pages free差值:若差值 - 用
pmap -x $(pgrep mysqld) | grep anon看MySQL进程的匿名页总量,对比innodb_buffer_pool_size是否接近(通常应占85%以上) -
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_wait_free';非零说明线程在等空闲页,背后大概率是刷脏页卡住 + Swap共同作用
真正卡点在于:Buffer Pool内存是匿名页,而Linux内核对匿名页没有“钉住内存”机制;哪怕你预留了足够available,只要NUMA绑错、numa_hit掉下去,内核就会把它当远端冷页优先换出——这不是配置漏了,是内存访问模式本身被破坏了。











