<p>应使用KILL QUERY而非KILL,以中断当前SQL语句而保持连接存活;通过SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 30 ORDER BY TIME DESC LIMIT 20快速定位高耗CPU查询,重点关注State为Sorting result、Sending data等的线程,并结合SHOW FULL PROCESSLIST查看完整SQL。</p>

立刻中断那条正在执行的SQL,而不是kill整个连接——用KILL QUERY,不是KILL。
怎么快速定位正在“烧CPU”的SQL
别等SHOW PROCESSLIST返回一堆Sleep线程再翻页。直接查information_schema.PROCESSLIST,过滤掉休眠态,按运行时长倒序:
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 30 ORDER BY TIME DESC LIMIT 20;- 重点盯
State列:出现Sorting result、Sending data、Creating sort index的,基本就是CPU密集型操作 - 如果大量线程卡在
Locked或Waiting for table metadata lock,说明不是SQL本身慢,而是被锁住了——得先查谁在持有MDL锁 -
INFO字段常被截断,真要确认SQL全貌,必须用SHOW FULL PROCESSLIST(注意权限,部分账号看不到)
为什么不能直接KILL而要用KILL QUERY
一个连接可能跑着多个语句,或者应用正复用连接做事务。直接KILL [id]会干掉整个连接,触发应用重连、事务回滚、连接池重建,反而引发雪崩。而KILL QUERY [id]只中断当前正在执行的语句,连接保活,CPU通常1秒内回落。
- 确认目标线程ID后,执行:
KILL QUERY 12345;(把12345换成实际ID) - 执行后立刻再跑一遍
SELECT ... FROM PROCESSLIST,看State是否变成Killed,且TIME不再增长 - 如果
State卡在Killed超过30秒,说明该语句正在清理资源(比如大临时表回写),此时不要重复KILL,耐心等它释放
EXPLAIN看到Using filesort或Using temporary怎么办
这两个提示不是警告,是判决书——说明MySQL正在用CPU做排序或建临时表。尤其当rows远大于结果集时,问题一定出在索引或条件设计上。
- 检查
ORDER BY字段是否落在联合索引最左前缀上;多字段排序时,ORDER BY a,b需要(a,b)索引,(b,a)无效 -
WHERE里带函数(如DATE(created_at))或运算(如price * 1.1 > 100)会失效索引,改写成范围条件 - 子查询尽量转为
JOIN,特别是IN (SELECT ...),MySQL 5.7之前容易退化成嵌套循环 - 临时调大
tmp_table_size和max_heap_table_size(比如设为512M),避免内存临时表溢出到磁盘,但这只是止血,不是根治
容易被忽略的“安静杀手”:统计信息过期和隐式类型转换
CPU飙高时,你看到的执行计划可能是错的——因为优化器基于过时的统计信息做了错误决策,或者字段类型不匹配导致全表扫描。
- 执行
ANALYZE TABLE your_table_name;强制更新统计信息,尤其在大批量导入/删除后 - 检查
EXPLAIN输出里的type是否为ALL,再看Extra有没有Using where; Using index——如果没有,查WHERE条件字段类型是否和列定义一致(比如user_id VARCHAR却传了数字123) -
information_schema.COLUMNS里确认字段类型,用SELECT HEX('123')和SELECT HEX(user_id)比对十六进制值,能快速暴露隐式转换
真正难的不是找到那条SQL,而是判断它为什么在这个时刻突然变慢——可能上周还跑得飞快,今天就卡死。索引没动、数据量没暴涨、QPS也没突增,但统计信息老化、字符集升级、甚至一次小版本补丁都可能让执行计划彻底偏移。盯住EXPLAIN的rows和key字段,比看CPU使用率更能说明问题。


















