95%以上mysql cpu飙升源于慢sql导致的逻辑读暴增;核心是使explain中rows值降一个数量级,并消除using filesort和using temporary。

直接结论:95%以上的MySQL CPU飙升,根源是慢SQL导致的逻辑读暴增,不是配置或硬件问题;重构核心不是“改写SQL”,而是让EXPLAIN里rows值下降一个数量级,同时消除Using filesort和Using temporary。
用slow_query_log确认哪些SQL真正在吃CPU
别信监控图表上的“CPU 100%”,先看它到底被谁拖垮。开启慢日志不是为了凑数,而是要拿到真实扫描行数与返回行数的比值:
-
SET GLOBAL slow_query_log = 'ON'+SET GLOBAL long_query_time = 1(业务敏感可设为0.5) - 必须同时打开
log_queries_not_using_indexes = ON,很多“不慢但高频”的SQL没进慢日志,却在持续刷Rows_examined - 重点盯日志里的
Rows_examined字段——如果它比Rows_sent大10倍以上(比如Rows_examined: 124800,Rows_sent: 12),这条SQL就是CPU杀手,优先处理 - 注意时间戳对齐:日志里
# Time:对应的是SQL开始执行时刻,不是记录写入时刻,排查时要结合top -Hp <mysqld_pid></mysqld_pid>线程快照交叉验证
用EXPLAIN定位执行计划里的三类硬伤
EXPLAIN不是看有没有索引,而是看MySQL实际怎么走——很多SQL明明建了索引,type还是ALL,key还是NULL:
-
type = ALL:全表扫描,立刻停掉。常见原因:WHERE条件用了函数(如DATE(create_time))、隐式类型转换(user_id是VARCHAR却传了数字)、OR连多个非索引列 -
Extra里出现Using filesort:说明ORDER BY字段没走索引。解决不是加单列索引,而是建联合索引把WHERE条件列+ORDER BY列一起覆盖,例如WHERE status = ? AND created_at > ? ORDER BY updated_at DESC,索引应为(status, created_at, updated_at) -
Extra里出现Using temporary:大概率是GROUP BY或DISTINCT触发了临时表。避免方式包括:确保GROUP BY字段有索引、用WHERE提前过滤数据量、拆分复杂聚合为多次查询
重构SQL时绕不开的四个坑
开发常以为“SQL变短=变快”,实际恰恰相反。真正有效的重构往往会让SQL更长、更明确:
- 别用
SELECT *:哪怕只少查1个TEXT字段,也能显著降低buffer pool压力和网络传输开销,尤其当Rows_examined很大时,这步省下的CPU不可忽略 -
IN列表超过500个值就拆:MySQL对大IN的优化很差,容易退化成全表扫描;改成JOIN临时表或分批次查更稳 -
LIMIT不能代替过滤:SELECT * FROM log WHERE type = 'error' ORDER BY id DESC LIMIT 10如果type选择性差(比如90%都是error),MySQL仍会扫描大量行才凑够10条,必须给type加索引,或改用覆盖索引+子查询 - 关联查询别堆
LEFT JOIN:每多一个JOIN,MySQL可能生成指数级的执行计划组合。优先用应用层两次查询+内存关联,或把中间结果落临时表再JOIN
验证重构是否真起效的唯一标准
上线后别只看QPS或响应时间,CPU水位是否回落,取决于Rows_examined是否真实下降。最可靠的方式是:
- 在测试环境用
SELECT ... INTO OUTFILE导出原始慢SQL的执行结果,确保语义一致 - 用
SHOW PROFILES对比重构前后Duration和Rows_examined,两者必须同步下降,否则只是掩盖问题 - 观察
SHOW STATUS LIKE 'Innodb_buffer_pool_read_requests'与Innodb_buffer_pool_reads比值——如果重构后前者大幅上升但后者没涨,说明逻辑读确实转移到内存,CPU压力自然释放
最容易被忽略的一点:索引不是越多越好。cardinality低的索引(比如性别字段)不仅无效,还会拖慢INSERT/UPDATE,并让优化器在生成执行计划时多花CPU做无谓判断。每次加索引前,先跑一遍SELECT COUNT(DISTINCT column_name)/COUNT(*) FROM table_name,低于0.01就别建。











