mysql卡但cpu低时90%是swap换页导致:先用vmstat 1确认si/so持续>1000 kb/s,再结合free -h看swapused是否上涨;需调vm.swappiness=1、配置memlock unlimited并启用innodb_use_sys_malloc=0。

MySQL卡但CPU很低?90%是Swap在换页,不是SQL或索引问题。
怎么确认是不是Swap在拖慢MySQL
别查慢日志、别看top的%Cpu——直接盯内存换页行为:
- 运行
vmstat 1,重点关注si(swap-in)和so(swap-out)两列,单位是KB/s;只要任一值持续 > 1000,就是Swap正在高频搬运页 - 同时跑
free -h,看SwapUsed是否持续上涨,哪怕只涨几十MB也危险 -
swpd > 0+si/so > 0同时成立,基本可锁定Swap问题 - 注意:
used内存高不等于危险,available持续低于1G且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,宿主机设置对容器无效
为什么只调swappiness还不够
vm.swappiness=1 是减缓,不是根治。它只降低内核“倾向”,不阻止 mysqld 进程本身被换出:
- 内存压力极大时,OOM Killer 仍可能把
mysqld整页踢进Swap,InnoDB Buffer Pool的LRU链表瞬间崩坏 - 真正让MySQL免疫Swap,得配
memlock:在/etc/security/limits.conf加mysql hard memlock unlimited和mysql soft memlock unlimited - 在
my.cnf的[mysqld]段加innodb_use_sys_malloc=0(尤其配jemalloc时) - 必须由root启动
mysqld,否则memlock不生效;验证方式:prlimit -p $(pgrep mysqld) | grep memlock,输出应为unlimited
永久生效必须写进配置并重载
只改运行时等于白干,重启后还是默认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 值改了、memlock 限制加了、MySQL是root启的、prlimit 验证过生效、容器里还单独设了 --memory-swappiness。少一个,Swap就可能在半夜悄悄卷土重来。











