确认swap拖慢mysql需实时交叉验证:运行vmstat 1看si/so是否持续>1000 kb/s,同时free -h看swapused是否上涨;swpd>0且si/so>0同时成立即锁定问题,此时cpu低、sql快、无锁争用均属正常表象。

MySQL卡但CPU很低,90%是Swap在换页,不是SQL慢、不是锁争用,而是mysqld进程的内存页正被内核疯狂换入换出。
怎么一眼确认是Swap在拖慢MySQL
别查慢日志、别盯top里的%Cpu——这些全是干扰项。真正可信的证据只有两个命令实时交叉验证:
- 运行
vmstat 1,紧盯si(swap-in KB/s)和so(swap-out KB/s)两列:只要任一值持续 > 1000,就已严重异常 - 同步运行
free -h,看SwapUsed是否持续上涨,哪怕只涨几十MB也危险 -
swpd > 0+si/so > 0同时成立,才构成闭环证据;仅used高不危险,available持续低于1G才是真警报
为什么调了vm.swappiness=1还是卡
vm.swappiness只是控制内核“倾向”,不是开关。设成1能压低换页概率,但挡不住OOM Killer在内存压力突增时把mysqld整页踢进Swap——Buffer Pool的LRU链表瞬间错乱,查询毛刺躲不掉。
- 临时生效:执行
sudo sysctl vm.swappiness=1(别用echo 1 > /proc/sys/vm/swappiness,sysctl会校验取值防静默失败) - 永久生效:写入
/etc/sysctl.conf末尾vm.swappiness=1,再执行sudo sysctl -p重载 - 验证:执行
sysctl vm.swappiness必须输出1,且cat /etc/sysctl.conf | grep swappiness能捞出那行
怎样让mysqld进程真正免疫Swap
光调swappiness是半截子工程。根治必须三件事并行到位,漏一不可:
- 在
/etc/security/limits.conf加两行:mysql soft memlock unlimited和mysql hard memlock unlimited - 在
my.cnf的[mysqld]段加:innodb_use_sys_malloc=0(尤其配jemalloc时) - mysqld必须由
root启动(systemd下检查User=mysql是否与limits用户一致),否则prlimit -p $(pgrep mysqld) | grep memlock不会显示unlimited - 验证权限:
cat /proc/$(pgrep mysqld)/status | grep -i "cap",输出中CapBnd必须含cap_ipc_lock
容器环境里vm.swappiness为什么不起作用
宿主机设置对容器完全无效。Docker默认继承宿主值但不继承sysctl,Kubernetes更需显式配置。
- Docker启动时必须加参数:
docker run --memory-swappiness=1 - Kubernetes需在Pod spec的
securityContext里配置sysctls,且节点kubelet要开启--allowed-unsafe-sysctls - 容器内
swapon --show输出为空≠Swap设备已关——得看宿主机是否真禁用了/swap.img
真正难的不是改哪一行配置,而是确认所有环节都闭环:swappiness值改了、memlock限制加了、MySQL是root启的、prlimit验证过生效、容器里还单独设了--memory-swappiness。任何一个断点,Buffer Pool就随时可能被撕开一道口子。











