MySQL数据库运行过程中如果出现响应延迟、查询卡顿的情况,除了SQL语句、索引问题外,系统SWAP异常使用也是需要重点排查的方向。SWAP是操作系统在物理内存不足时,将部分内存数据交换到磁盘上的交换空间,由于磁盘IO速度远低于内存,一旦MySQL频繁使用SWAP,就会直接导致数据库性能大幅下降。

第一步:确认系统SWAP整体使用情况
首先需要通过系统命令查看当前SWAP的整体使用状态,判断是否存在SWAP被大量占用的情况。常用的查看命令如下:
# 查看SWAP总大小、已使用大小、空闲大小 free -h # 查看SWAP的挂载设备和优先级 swapon -s # 实时查看系统内存、SWAP、CPU使用情况 top
如果free -h命令输出中Swap行的used值不为0,且占用了较大比例,或者top命令中看到系统整体内存使用率接近100%,同时SWAP使用量持续上升,就说明系统已经出现了内存不足触发SWAP的情况。
第二步:定位占用SWAP的进程
确认SWAP被使用后,需要进一步找到是哪个进程占用了大量SWAP,尤其是确认是否是MySQL进程导致的。可以通过smem命令或者top命令的扩展选项来查看进程的SWAP占用:
# 安装smem工具(CentOS系统) yum install smem -y # 查看所有进程的SWAP占用,按SWAP使用量降序排列 smem -t -k -p | sort -k 5 -nr # 或者直接在top命令中按f键,添加SWAP列,查看各进程SWAP占用
如果输出中MySQL进程的SWAP占用数值较高,就可以初步判定数据库卡顿和SWAP有关。如果SWAP占用最高的是其他进程,则需要先处理对应进程的内存占用问题,再观察MySQL性能是否恢复。
第三步:分析MySQL内存配置是否合理
MySQL自身的内存配置不合理是导致SWAP被占用的常见原因,需要检查MySQL的核心内存参数是否符合服务器实际内存情况。可以通过MySQL客户端执行以下命令查看配置:
-- 查看InnoDB缓冲池大小,这是MySQL占用内存最大的参数 SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; -- 查看每个连接的最大内存占用 SHOW VARIABLES LIKE 'sort_buffer_size'; SHOW VARIABLES LIKE 'join_buffer_size'; SHOW VARIABLES LIKE 'read_buffer_size'; -- 查看最大连接数 SHOW VARIABLES LIKE 'max_connections';
如果innodb_buffer_pool_size设置超过了服务器物理内存的70%,或者sort_buffer_size等单连接参数设置过大,同时max_connections数值很高,就会导致MySQL总内存需求超过物理内存,进而触发SWAP。需要根据服务器实际内存调整这些参数,比如16G内存的服务器,innodb_buffer_pool_size建议设置为10G左右。
第四步:检查系统内存分配策略
除了MySQL自身配置,系统的内存分配策略也可能导致SWAP被提前使用。可以查看系统的vm.swappiness参数:
# 查看系统swappiness值,默认通常是30或者60 cat /proc/sys/vm/swappiness # 临时调整swappiness值为10,降低系统使用SWAP的倾向 sysctl vm.swappiness=10 # 永久调整,写入配置文件 echo "vm.swappiness=10" >> /etc/sysctl.conf sysctl -p
swappiness的取值范围是0到100,数值越高系统越倾向于使用SWAP,数值越低越倾向于释放文件缓存来腾出内存给应用。对于运行MySQL的服务器,建议将该值设置为10以下,减少不必要的SWAP使用。
第五步:验证优化效果
完成上述排查和优化后,需要持续观察数据库性能是否恢复,同时监控SWAP使用情况:
# 持续监控内存和SWAP变化 watch -n 1 free -h # 查看MySQL慢查询情况,确认卡顿是否消失 SHOW VARIABLES LIKE 'slow_query_log'; SHOW STATUS LIKE 'Slow_queries';
如果优化后SWAP使用量逐步下降,最终回到0或者极低水平,同时数据库查询响应速度恢复正常,慢查询数量不再异常增长,就说明SWAP导致的卡顿问题已经解决。
常见问题总结
- 如果服务器物理内存确实不足,除了调整MySQL配置,还需要考虑升级服务器内存,从根源上避免SWAP被使用。
- 如果MySQL进程占用的SWAP很高,但是系统还有空闲内存,可能是MySQL的内存没有及时释放,可以尝试重启MySQL实例释放SWAP占用,但重启前需要做好数据备份。
- 定期监控服务器内存和SWAP使用情况,提前发现内存增长趋势,避免出现突发卡顿问题。