应先查INFORMATION_SCHEMA.PROCESSLIST定位高耗SQL,再用EXPLAIN验证全表扫描;重点看STATE为Sending data等、type=ALL或rows接近表总行数的语句,紧急时用KILL QUERY终止。

MySQL 5.7 CPU 占用 100% 时,别急着调参或重启,90% 的情况是某几条 SQL 正在“死磕”CPU——必须在 3 分钟内从 PROCESSLIST 里揪出它们,并用 EXPLAIN 验证是否全表扫描。
查 INFORMATION_SCHEMA.PROCESSLIST 抓实时高耗 SQL
直接查系统表比 SHOW PROCESSLIST 更可靠,它不截断 SQL、可加条件过滤、能排序定位:
- 执行
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 30 ORDER BY TIME DESC LIMIT 20,重点看STATE列:出现Sending data、Sorting result、Creating sort index的线程,基本就是 CPU 密集型操作 -
INFO字段可能被截断,若看到疑似慢 SQL,用SELECT INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = ?单独查完整语句 - 如果结果里全是
Sleep,说明高 CPU 来自后台线程(如 InnoDB purge 或刷脏页),需立刻执行SHOW ENGINE INNODB STATUS查BACKGROUND THREAD部分
用 EXPLAIN 快速识别全表扫描
对抓到的可疑 SQL 加 EXPLAIN 前缀执行,盯住三列:type、rows、key:
-
type = ALL是明确信号:MySQL 正在逐行扫表;rows接近该表COUNT(*)结果,坐实全表扫描 -
type = index看似好,实为按索引顺序全扫索引树,尤其当索引字段大或数据量大时,CPU 消耗不亚于ALL -
key为NULL说明索引根本没被选中,哪怕WHERE条件看起来能走索引——常见于隐式类型转换、函数包裹字段(如WHERE DATE(create_time) = '2026-09-02')
紧急止血:KILL QUERY 而非 KILL
杀错线程会引发应用重连风暴,必须精准中断语句本身:
- 优先 kill
STATE = 'Sending data'且TIME > 60的线程,这类通常在扫大表或做大排序,kill 后 CPU 会立刻回落 - 务必用
KILL QUERY [id](不是KILL [id]),前者只中断当前语句,连接保活,避免应用层反复建连 - 若发现大量线程卡在
Locked或Waiting for table metadata lock,先查谁 hold 锁:SELECT * FROM performance_schema.threads WHERE PROCESSLIST_COMMAND = 'Query' AND PROCESSLIST_TIME > 60
别忽略系统层干扰:先确认是不是 mysqld 在吃 CPU
top 里看到 CPU 100%,未必是 MySQL 的锅:
- 执行
top -p $(pgrep mysqld),确认 %us(用户态)占比高;如果 %sy(内核态)异常高,大概率是锁争用或上下文切换压力大 - 用
vmstat 1看cs(context switch):持续 > 10k/s 表示线程调度过载,可能是连接数暴增或thread_cache_size设置过小 -
wa(I/O wait)很低但 CPU 高,基本排除磁盘瓶颈,问题一定出在计算逻辑上——比如没索引的GROUP BY或ORDER BY
真正难的不是找到那条慢 SQL,而是判断它为什么没走索引:字段类型不一致、字符集不同、统计信息过期、或者优化器误判。这些不会在 EXPLAIN 里直接写出来,得结合 SHOW INDEX 和 ANALYZE TABLE 交叉验证。


















