确认mysqld被换出到swap导致io卡顿,需用vmstat 1实时监控si/so列持续>1000 kb/s,并结合free -h中swpd>0与si/so>0闭环验证;根本解决须三者并行:调低vm.swappiness、配置memlock unlimited锁定内存、设置innodb_use_sys_malloc=0。

mysqld 进程被换出到 Swap,不是“慢”,是“卡在磁盘IO上”——InnoDB Buffer Pool 里的热页被踢进磁盘,每次访问都要等 si(swap-in)把页拉回来,延迟从纳秒级跳到毫秒级,事务自然毛刺不断。
怎么确认是 Swap 在拖慢 MySQL 响应
-
vmstat 1是唯一可信的实时证据:盯住si和so两列,单位 KB/s - 只要任一值持续 > 1000,就说明内存页正在高频换入换出
-
free -h里SwapUsed非零只是结果,swpd > 0+si/so > 0同时成立才构成闭环证据 - 别信
top里mysqld的%Cpu:CPU 低 ≠ 没问题,恰恰是 Swap 搬运阻塞了执行线程
为什么调 vm.swappiness=1 还不够
-
vm.swappiness控制的是内核“倾向”,不是开关:设成 1 只降低换页概率,不阻止mysqld被换出 - 内存压力突增时,OOM Killer 仍可能整页踢走
mysqld,Buffer Pool 的 LRU 链表瞬间失序 - 必须配
memlock unlimited:在/etc/security/limits.conf加两行mysql hard memlock unlimitedmysql soft memlock unlimited - 并在
my.cnf的[mysqld]段加innodb_use_sys_malloc=0(尤其用 jemalloc 时) - 启动必须由 root 执行,否则
CapBnd里缺cap_ipc_lock,memlock形同虚设
容器环境里 vm.swappiness 不生效怎么办
- 宿主机设置对容器完全无效,Docker 默认继承宿主值但不继承 sysctl
- 启动容器时必须显式传参:
docker run --memory-swappiness=1 - Kubernetes 中需在 Pod spec 的
securityContext里配置sysctls,且节点 kubelet 要开启--allowed-unsafe-sysctls -
swapon --show在容器内输出为空,不代表 Swap 设备已关——得看宿主机是否真禁用了/swap.img
真正让 mysqld 免疫 Swap 的,从来不是调一个参数,而是三件事同时到位:swappiness 压低、memlock 锁死、innodb_use_sys_malloc=0 配合。漏掉任意一个,Buffer Pool 就随时可能被撕开一道口子。











