如何排查MySQL查询引发的CPU持续100%异常问题?
排查MySQL高CPU占用问题的步骤
一、实时定位当前运行的异常查询
- 通过phpMyAdmin查看MySQL进程:
- 登录phpMyAdmin,切换到状态标签页
- 进入进程模块,筛选正在运行的
Query类型进程 - 重点关注
Time列数值过大(如超过30秒)、Info列显示完整SQL的进程,这类就是可能导致CPU持续高负载的源头
- 也可直接在SQL控制台执行命令查询:
结果中的SHOW FULL PROCESSLIST; -- 过滤出运行超过10秒的查询 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND TIME > 10;Info字段会显示具体执行的SQL语句,直接定位目标。
二、分析查询执行计划
对高频查询执行EXPLAIN,排查性能瓶颈:
针对查询1:
EXPLAIN SELECT DISTINCT p.Order , p.Delivery, p.Rowing, e.Path, e.Fecha, t.numTram_tr, t.name_tr, t.lastname_tr, t.sex_tr, t.document_tr, t.ejem_tr, t.Delivery_tr, t.Birthday_tr, t.fechaEmision_tr, t.cod_tr, t.ImgFrenteDni_tr, t.ImgDorsoDni_tr from `Order` p INNER JOIN Delivery e ON p.Delivery= e.Delivery left JOIN transport t ON p.Delivery= t.Delivery_tr WHERE p.Order = '972022';
重点检查:
type列:如果显示ALL,说明存在全表扫描,尤其注意transport表的Delivery_tr字段——虽然Delivery是主键,但transport.Delivery_tr若无索引,LEFT JOIN会触发全表扫描,消耗大量CPUExtra列:若出现Using temporary或Using filesort,说明DISTINCT操作需要临时表排序,会大幅增加计算负载- 确认
DISTINCT必要性:如果JOIN逻辑本身不会产生重复数据,去掉DISTINCT可减少不必要的计算
针对查询2:
EXPLAIN SELECT e.Entrega, p.Pedido, p.Remito, e.Fecha from Entrega e INNER JOIN Pedido p ON e.Entrega = p.Entrega WHERE e.Fecha BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59' GROUP BY e.Delivery, p.Order, p.Rowing ORDER BY e.Fecha ASC;
重点检查:
- 字段一致性:原查询中
ORDER BY e.date与SELECT里的e.Fecha可能是笔误,字段不匹配会导致排序逻辑错误甚至全表扫描 - GROUP BY合法性:当前SELECT列与GROUP BY列不对应,违反MySQL默认的
ONLY_FULL_GROUP_BY模式,不仅结果不确定,还会触发额外计算 - 索引有效性:检查
Entrega.Fecha是否有单独索引,是否创建了(Fecha, Entrega)复合索引覆盖WHERE+JOIN+GROUP BY需求;同时确认Pedido.Entrega(JOIN条件)是否有索引 - 日期格式问题:原查询中的
24:00:00是无效时间格式,MySQL会解析为次日00:00:00,导致查询范围超出预期,返回大量数据
三、服务器与连接池排查
- 检查MySQL连接数:执行
SHOW STATUS LIKE 'Threads%';,若Threads_running数值过高,说明并发查询超出服务器承载能力 - 确认连接释放:虽然用了
using(MySqlConnection),但排查代码中是否存在查询未完成就中断、事务未提交/回滚的情况,避免连接被无效占用 - 定位CPU归属:用
top(Linux)或任务管理器(Windows)确认高CPU进程是mysqld还是其他程序,排除前端DataTables未做数据库分页、加载大量数据导致的服务器CPU负载
四、临时验证与优化
- 找到异常查询后,执行
KILL [进程ID];终止进程,观察CPU是否回落,验证是否为该查询导致的问题 - 优化查询后,在测试环境模拟高频调用,观察CPU变化情况
需要补充的信息:
- 两个查询的
EXPLAIN执行结果 - CPU高占用时
SHOW FULL PROCESSLIST的输出内容 transport表的结构与索引配置- 查询2中日期参数拼接后的实际SQL语句
内容的提问来源于stack exchange,提问作者popo
相关产品推荐
相关产品推荐

