MySQL事务响应变慢但CPU低,90%是Swap换页导致;用vmstat 1盯si/so列,持续>1000 KB/s即确认;调swappiness=1并sysctl -p生效,再配memlock unlimited和innodb_use_sys_malloc=0方可根治。

MySQL事务响应变慢但CPU很低?90%是Swap在偷偷换页,不是SQL或索引问题。
怎么快速确认是不是Swap在拖慢事务
别猜,直接看实时换页指标。vmstat 1 每秒刷新一次,盯住 si(swap-in)和 so(swap-out)两列:
- 只要
si或so持续 > 1000 KB/s,就是Swap正在高频搬运内存页,InnoDB Buffer Pool里的热数据页被反复踢出、拉回,事务延迟必然飙升 -
free -h里SwapUsed非零只是“结果”,vmstat才是“过程证据” - 注意:
used内存高 ≠ 危险;available持续 swpd 上涨,才是真警报
临时压住Swap换页冲动:立刻生效的命令
线上不能等重启,用 sysctl 直接改倾向值:
- 执行
sudo sysctl vm.swappiness=1(不是echo 1 > /proc/sys/vm/swappiness,sysctl会校验取值范围,防输错静默失败) - 改完马上
watch -n1 'cat /proc/sys/vm/swappiness'看几秒,防某些运维脚本自动回滚 - 同时观察
vmstat 1:如果si/so从千级掉到个位数,基本锁定Swap是元凶 - 容器内MySQL要额外检查:
docker run是否加了--memory-swappiness=1,宿主机设置对容器无效
永久生效必须写进配置并重载
只改运行时等于白干,重启后还是默认60:
- 编辑
/etc/sysctl.conf,末尾追加一行:vm.swappiness=1 - 执行
sudo sysctl -p重载——这步漏掉,配置就永远不生效 - 验证:
sysctl vm.swappiness必须输出1,且cat /etc/sysctl.conf | grep swappiness能捞出那行 - 别往
/etc/sysctl.d/下乱建conf文件:部分发行版加载顺序不保证,sysctl -p可能不读
为什么只调swappiness还不够
vm.swappiness=1 是减缓,不是根治。它只降低内核“倾向”,不阻止MySQL进程本身被换出:
- 内存压力极大时,OOM Killer仍可能把
mysqld进程整页踢进Swap,Buffer Pool LRU链表瞬间崩坏 - 真正让MySQL免疫Swap,得配
memlock:在/etc/security/limits.conf加mysql hard memlock unlimited,并在my.cnf的[mysqld]段加innodb_use_sys_malloc=0(若用jemalloc) - 启动必须用root权限,否则
memlock不生效;systemd下还要检查服务用户是否与limits一致 - NUMA架构服务器上,不配
innodb_numa_interleave=1,memlock可能白开
Swappiness调低后事务延迟下降,不代表Swap彻底退出舞台——它还在,只是被关进了小黑屋。真正让MySQL进程“锁死”在物理内存里,才是避免某次备份或大导入突然卡死的关键动作。


















