确认MySQL卡顿由Swap导致:先运行vmstat 1,若si或so持续>1000 KB/s,再结合free -h发现SwapUsed持续上涨,且swpd>0与si/so>0同时成立,即可锁定Swap问题;此时used高不危险,available持续低于1G才需警惕。

MySQL卡但CPU很低,90%是Swap在换页,不是SQL慢、不是锁争用——先盯si和so,别查慢日志。
怎么确认MySQL卡顿真是Swap导致的
别看top里mysqld的%Cpu,也别急着开慢查询日志。真实信号藏在内存换页行为里:
- 运行
vmstat 1,紧盯si(swap-in)和so(swap-out)两列,单位是KB/s;只要任一值持续 > 1000,就已严重异常 - 同步跑
free -h,观察SwapUsed是否持续上涨,哪怕只涨几十MB也危险 -
swpd > 0且si/so > 0同时成立,基本可锁定Swap问题 - 注意:
used内存高不危险,available持续低于1G才真警报
临时压住si/so:立刻生效的sysctl调法
线上不能等重启,直接改内核倾向值,但必须用对命令:
- 执行
sudo sysctl vm.swappiness=1(不是echo 1 > /proc/sys/vm/swappiness,前者会校验取值防静默失败) - 改完立刻
watch -n1 'cat /proc/sys/vm/swappiness'盯几秒,防运维脚本自动回滚 - 同步观察
vmstat 1:若si/so从千级掉到个位数,说明Swap确实是元凶 - 容器内MySQL要额外检查:
docker run是否加了--memory-swappiness=1,宿主机设置对容器无效
为什么调完swappiness还是卡:memlock没配或没生效
vm.swappiness=1只是减缓,不是根治。内核压力大时仍可能把mysqld整页踢进Swap,Buffer Pool的LRU链表瞬间崩坏:
- 在
/etc/security/limits.conf追加两行:mysql hard memlock unlimited和mysql soft memlock unlimited - 在
my.cnf的[mysqld]段加innodb_use_sys_malloc=0(尤其配jemalloc时) - 必须由root启动mysqld;验证方式:
prlimit -p $(pgrep mysqld) | grep memlock,输出应为unlimited - NUMA架构下(如多路Xeon),memlock可能白开:需额外配
innodb_numa_interleave=ON或用numactl --interleave=all
永久生效必须闭环验证:三步缺一不可
只改运行时等于白干,重启后还是默认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可能不读 - 云主机(如Ubuntu 20.04+)还要确认Swap设备是否真关了:
swapon --show输出为空才算
最常被忽略的点是:prlimit验证没做、容器没单独设--memory-swappiness、NUMA机器漏配innodb_numa_interleave——这些地方一漏,si/so随时可能卷土重来。


















