MySQL卡顿但CPU低?90%的锅在Swap,先别急着调my.cnf 当MySQL响应变慢,监控却显示CPU使用率不高时,你是否感到熟悉?先别急着翻找my.cnf里的缓存参数,一个更常见的“隐形杀手”往往被忽略了——Swap(交换分区)。十有八九,问题就出在它身上。 核心判断很直接:MySQL卡顿
当MySQL响应变慢,监控却显示CPU使用率不高时,你是否感到熟悉?先别急着翻找my.cnf里的缓存参数,一个更常见的“隐形杀手”往往被忽略了——Swap(交换分区)。十有八九,问题就出在它身上。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
核心判断很直接:MySQL卡顿但CPU很低,90%的概率是Swap在拖后腿。第一步不是禁用Swap,而是检查关键内核参数vm.swappiness,看它是否被设成了像60这样的“高危”默认值。
vm.swappiness值危险吗?打开终端,执行命令:
sysctl vm.swappiness
如果输出是60或更高,那么你已经踩中了数据库服务器的典型配置雷区。这个值对桌面系统可能无所谓,但对MySQL这类极度依赖内存性能的服务来说,vm.swappiness=60意味着:只要系统内存使用率超过40%,内核就可能开始积极地将内存中的匿名页(如InnoDB Buffer Pool里的关键数据页)挪到Swap分区。磁盘I/O速度比内存慢3到4个数量级,性能损耗可想而知。
需要厘清的关键点是:vm.swappiness本身不反映Swap当前是否正在使用,只代表内核“倾向于”使用Swap的程度。因此,即使free -h显示SwapUsed为0,只要这个倾向值还是60,系统内存压力稍大,Swap这个“闸门”就可能打开。
vm.swappiness设置在1到10之间。1最为激进,尽可能避免交换;10则稍显稳妥,给系统留一点弹性空间。vm.swappiness=0不会彻底禁止Swap,它只是告诉内核“除非内存快用尽(OOM前),否则别考虑Swap”。Swap设备本身还在,一旦触发,swpd(已用交换区)非零、si/so(换入/换出)指标飙高的情况照样会发生。/swap.img文件作为交换分区。仅修改sysctl参数可能不够,最好用swapon --show命令确认,输出为空才表示Swap确实没被激活。vm.swappiness,立即验证效果线上环境等不及重启,需要立刻调整参数来观察效果。执行以下命令,将倾向值压到最低:
sudo sysctl vm.swappiness=1
执行后,马上打开另一个终端,运行vmstat 1,重点观察si(每秒从磁盘换入的内存量)和so(每秒换出到磁盘的内存量)这两列。如果之前它们持续高于1000 KB/s,调整后迅速下降到0或个位数,那么基本可以锁定Swap是导致性能卡顿的元凶。
sysctl命令? 虽然直接echo 1 > /proc/sys/vm/swappiness也能生效,但sysctl命令会进行取值范围的校验,能避免因输入错误导致内核静默失败。--memory-swappiness=1参数,宿主机上的这个设置对容器是无效的。watch -n1 'cat /proc/sys/vm/swappiness'命令盯几秒钟,防止一些自动化运维脚本又把参数改回去。临时生效只是测试,要永久解决问题,必须修改配置文件。编辑系统参数配置文件:
sudo nano /etc/sysctl.conf
在文件末尾添加一行:
vm.swappiness=1
保存退出后,务必执行以下命令让配置立即生效:
sudo sysctl -p
这一步千万不能漏!很多团队改了文件却忘了执行重载命令,等服务器重启后才发现参数又变回了60,问题依旧。
/etc/sysctl.d/目录下随意创建新的.conf文件,因为不同发行版的配置加载顺序可能不确定,sysctl -p可能不会读取它们。sysctl vm.swappiness确认输出为1,同时用cat /etc/sysctl.conf | grep swappiness确保那行配置确实存在。sysctl reload或等价的步骤,不能仅仅拷贝配置文件了事。调低vm.swappiness只是降低了内核交换内存的“倾向”,并不等于MySQL进程的内存就绝对安全了。要根治Swap导致的性能问题,通常需要三管齐下:
/etc/security/limits.conf文件,添加以下两行,允许MySQL进程锁定内存不被换出:
mysql soft memlock unlimited
mysql hard memlock unlimited
my.cnf的[mysqld]段中,增加一行:
innodb_flush_method=O_DIRECT
这可以避免双缓冲,减少对操作系统缓存的压力。prlimit -p $(pgrep mysqld) | grep memlock
输出结果中的memlock值必须是unlimited,否则说明内存锁配置没有生效。这里有一个最容易被忽略的坑:虽然配置了memlock,但如果my.cnf中innodb_buffer_pool_size设置得过大(比如占了物理内存的85%以上),MySQL服务可能会启动失败。而且,这种失败有时是“静默”的——通过systemctl status mysql可能看到的是“active (running)”,但实际上需要查看系统日志(journalctl -u mysql)才能发现Cannot allocate memory这样的报错。因此,调整Buffer Pool大小时,务必为操作系统和其他进程预留足够的内存空间。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述