VPS上的MySQL突然变慢怎么办?从慢查询日志到EXPLAIN定位

数据库慢不只看一条SQL:日志样本、执行计划、锁等待与整机资源要放在同一时间轴
发布于
3

VPS上的MySQL突然变慢,不应一开始就增加内存或修改大量参数。先确认慢的是单条SQL、某类请求,还是整个服务器;随后在受控时间窗采集慢查询、锁等待和系统资源证据。慢查询日志能告诉你“哪些语句超过阈值”,EXPLAIN帮助判断执行计划,但两者都不能脱离CPU、内存、磁盘和业务并发单独解释。

先判断数据库慢在哪一层

症状 更可能的方向 先查什么
所有查询同时变慢 CPU、磁盘I/O、内存回收或连接拥塞 top、vmstat、iostat、连接数
某个接口或报表慢 SQL扫描、排序、临时表或索引问题 慢查询样本与EXPLAIN
写入期间读写一起卡住 锁等待、长事务或热点行 当前事务和锁等待
流量不高却周期性变慢 备份、日志轮转、定时任务或检查点 时间轴与系统任务
连接建立慢或报满 连接池、DNS、认证或连接上限 连接状态与应用池配置

记录准确时间和时区很重要。数据库日志、应用日志和VPS监控只有放在同一时间轴,才能判断因果顺序。

先查看当前慢查询配置

在有管理权限且了解影响范围的前提下,可先只读查询:

SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'slow_query_log_file';
SHOW VARIABLES LIKE 'long_query_time';
SHOW VARIABLES LIKE 'log_queries_not_using_indexes';

long_query_time决定超过多长时间才记录。没有适用于所有数据库的固定阈值:在线接口、报表和批处理对延迟的要求不同。阈值过高会漏掉有业务影响的查询,过低则可能制造大量日志和额外I/O。

log_queries_not_using_indexes也不应长期盲目开启。小表全扫可能很快,开启后日志量可能激增;是否记录应结合短时诊断目标。

怎样短时开启慢查询日志

生产环境修改前先确认MySQL或兼容发行版的版本、配置文件位置、磁盘余量和变更回滚。可在维护流程中使用运行时变量进行短时观察:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;

上面的1秒只是演示值,不是推荐阈值。运行时设置可能在重启后失效;写入配置文件则会持久生效,语法和文件位置取决于当前发行版。诊断完成后应恢复原设置,并确认日志文件权限、轮转和磁盘占用。

不要把包含密码、个人数据或业务敏感参数的完整SQL直接发布。导出样本前应脱敏,并限制访问权限。

从慢日志里挑出真正值得查的SQL

不要只按单次最慢排序。至少记录:

  • 执行次数和总耗时;
  • 单次执行时间与分布;
  • 检查行数和返回行数;
  • 锁等待时间;
  • 发生时间、数据库和调用接口;
  • SQL是否只是参数不同的同一模板。

一条偶发的报表查询可能单次很慢,但高频中等慢查询的总资源消耗更大。应先按SQL模板聚合,再结合业务重要性排序。使用日志分析工具前核对其版本和脱敏方式,不要把生产日志上传到未知服务。

用EXPLAIN检查执行计划

对经过脱敏、可安全复现的SELECT查询,可在测试环境或低风险时间窗使用:

EXPLAIN SELECT ...;

重点观察访问类型、可能使用的索引、实际选中的索引、预计扫描行数,以及是否出现额外排序或临时表等信息。字段名称和输出能力会随MySQL版本变化。

EXPLAIN展示的是优化器计划,不等于完整运行时事实。部分版本支持更深入的执行分析,但可能真正运行查询;在生产环境使用前必须确认副作用和负载,尤其不能对写语句或高成本查询盲目执行。

没有使用索引就一定要加索引吗

不一定。小表全扫可能比走索引更快,低选择性列的单列索引也可能帮助有限。新增索引会增加磁盘空间、写入成本和维护开销。

判断前先核对:

  • WHERE、JOIN、ORDER BY和GROUP BY实际使用哪些列;
  • 联合索引的列顺序是否匹配主要查询;
  • 条件是否对索引列做了函数或隐式类型转换;
  • 返回数据是否过多,应用是否本可分页或缩小字段;
  • 统计信息是否过时,数据分布是否已经变化。

索引调整应先在接近生产数据分布的环境验证,并准备回退。不要在高峰期直接为大表建立索引。

别漏掉锁等待和长事务

SQL本身执行计划正常,也可能因为等待其他事务而变慢。应结合当前MySQL版本支持的系统视图查看运行中的事务、锁等待和连接状态。重点找持续时间异常的事务、未提交连接和批量写入。

不要为了“解除卡顿”直接批量终止连接。先确认事务用途和回滚成本;大型事务被终止后,回滚过程本身也可能持续占用I/O和锁。

把数据库证据和VPS资源放到一起

vmstat 1 5
iostat -xz 1 5
free -h

慢查询发生时,如果磁盘等待和队列同步上升,应查日志、临时表、排序、备份与云盘延迟;如果CPU运行队列高,检查高频SQL和并发;如果available持续低、换页活跃,则要核对数据库缓冲池与其他进程的共同工作集。

单纯把缓冲池、连接上限或缓存参数调大,可能把压力转移到内存或让并发争用更严重。参数调整应基于当前版本、数据规模和采样证据。

修复后怎样证明真正变快

  1. 保留修改前的SQL模板、执行计划、执行时间分布和系统资源。
  2. 在测试环境或受控窗口修改SQL、索引或应用调用方式。
  3. 使用相同参数范围和接近的数据分布复测。
  4. 观察接口延迟、扫描行数、锁等待、CPU和磁盘I/O是否同时改善。
  5. 持续观察一个完整业务周期,确认没有写入放大和新回归。

只看一次EXPLAIN或一次查询变快不够。缓存冷热、并发和数据分布都会影响结果,必须使用同口径对照。

结论

VPS上的MySQL变慢,应先按整机资源、锁等待和SQL执行计划三条线分层。用短时慢查询日志找样本,用EXPLAIN判断扫描与索引,再把结果与VPS的CPU、内存和I/O对齐。任何索引或参数修改都应经过可回退的验证,而不是凭单条日志直接上线。

常见问题(FAQ)

VPS上的MySQL突然变慢先查什么?
先确认是所有查询、某个接口还是写入锁等待,再把应用日志、数据库状态和VPS的CPU、内存、磁盘I/O放到同一时间轴。
MySQL慢查询日志可以一直开启吗?
是否长期开启取决于阈值、日志量、磁盘和运维策略。诊断时应先核对配置与磁盘余量,短时采集后恢复设置并安排轮转。
EXPLAIN会真正执行SQL吗?
普通EXPLAIN主要展示优化器计划;某些更深入的分析方式可能实际运行查询。使用前要核对当前MySQL版本和副作用。
MySQL查询没有使用索引就必须新建索引吗?
不一定。小表全扫可能更快,低选择性索引帮助有限,新增索引还会增加空间和写入成本,应结合查询条件、数据分布与复测结果决定。

本文由作者原创/授权发布于极跃圈(jiyueip.com)未经许可,禁止转载。题图来自Unsplash,基于CC0协议。

声明:极跃圈(JIYUEIP.com)内网友所发表的所有内容及言论仅代表其本人,并不反映任何极跃圈(JIYUEIP.com)之意见及观点。

0 讨论
热门最新
总结
暂无总结
0 / 600

VPS用着用着突然变卡,网站打开要好几秒、SSH敲命令有明显延迟——这种情况比完全断连更难排查。不是挂了,是慢了。本文用四个命令分别定位CPU、内存、磁盘IO和网络的瓶颈,告诉你性能卡在哪个环节。 排查前的第一步:确认不是自己的网络问题 很