swappiness=0不能根治抖动,因内存耗尽时内核仍会换页;o_direct需配合noatime、barrier=0等挂载参数才能绕过page cache,否则退化;须用strace验证io_submit是否生效,并用numastat排查numa伪抖动。

为什么swappiness=0不能直接解决抖动
设成 vm.swappiness=0 只是告诉内核“尽量不用 Swap”,但不等于禁用。当物理内存真的耗尽(比如 Buffer Pool 配得过大、其他进程吃光剩余内存),Linux 仍会触发 si/so 换页,查询线程卡在缺页中断里,表现为毫秒级延迟突增。这不是配置没生效,而是内存压力已穿透策略边界。
innodb_flush_method=O_DIRECT 要配合关闭文件系统缓存
该参数让 InnoDB 绕过 OS Page Cache 直写磁盘,避免双重缓存导致的内存虚高和 Swap 倾向。但必须确保:
- MySQL 数据目录所在文件系统不启用
atime(挂载时加noatime) - 禁用 ext4 的
barrier(若使用 SSD 且有掉电保护)——否则O_DIRECT会退化为带缓存写入 - 验证是否真正生效:用
strace -e trace=io_submit,write,pread64 -p $(pgrep mysqld)观察是否有write()调用;若有,说明仍在走 Page Cache
查清是不是 NUMA 导致的伪 Swap 抖动
现象是 vmstat 显示 si/so 波动,但 free -h 显示可用内存充足。这时很可能是 MySQL 进程跨 NUMA 节点分配内存,触发远端内存访问 + 隐式换页。关键检查点:
- 运行
numastat -p $(pgrep mysqld),看numa_miss是否持续 >5%,numa_hit是否 - 确认 systemd service 文件中是否包裹了
numactl --interleave=all或--cpunodebind=0 - 避免
MemoryAccounting=true—— 它会让 cgroup 强制回收内存,干扰内核 NUMA 感知逻辑
Buffer Pool 大小不是越大越好
抖动常发生在 Buffer Pool 占用内存达物理内存 75% 以上时,尤其搭配大量连接或临时表。真实风险点在于:
- InnoDB 内部结构(如
log_sys、dict_sys)也吃内存,总开销比配置值高 10–15% - OS 需要至少 2–4GB 空闲内存保底,否则 kswapd 会高频扫描并提前触发 Swap
- 用
cat /proc/meminfo | grep -E "MemFree|MemAvailable|SwapCached"对比MemAvailable和 Buffer Pool 配置值,差值建议 ≥3GB
innodb_buffer_pool_size,它只是冰山一角。











