<p>应先用top确认mysqld进程CPU占用及%sy、cs、wa指标,再执行SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 30 ORDER BY TIME DESC LIMIT 20定位高耗时活跃SQL,重点分析State为Sorting result等的语句,并结合锁等待和统计信息过期情况综合排查。</p>

直接杀掉长事务或重启 MySQL 只能抢几秒时间,真正要稳住业务,得在 5 分钟内定位到那几条“烧 CPU”的 SQL,并临时止血。慢查询是最大嫌疑,但不是唯一原因——锁争用、配置突变、统计信息过期都可能让 CPU 瞬间拉满。
确认是不是 MySQL 进程真正在吃 CPU
别急着进数据库,先看系统层有没有干扰:
- 执行
top,按Shift+P排序,确认占用 CPU 最高的确实是mysqld进程(不是 backup 脚本、logrotate 或某个 Java 应用) - 检查
%sy(内核态 CPU)是否异常高:如果是,可能是大量锁等待或上下文切换,不是 SQL 本身的问题 - 用
vmstat 1看cs(context switch)是否飙升 —— 超过 10k/s 就说明线程调度压力大,大概率是连接数暴增或 thread_cache_size 不够 - 注意
wa(IO wait)是否低:如果 wa 很低但 CPU 高,基本排除磁盘瓶颈,问题就在计算密集型操作上
快速抓出正在“烧 CPU”的活跃 SQL
SHOW PROCESSLIST 是第一反应动作,但它默认只显示前 100 行,且不包含完整 SQL。必须用更狠的组合:
- 执行
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 30 ORDER BY TIME DESC LIMIT 20;—— 抓出运行超 30 秒的非休眠线程 - 重点关注
State列:出现Sorting result、Sending data、Creating sort index的,基本就是 CPU 密集型操作 - 如果看到大量线程卡在
Locked或Waiting for table metadata lock,别查 SQL,先查谁在 hold 锁:SELECT * FROM performance_schema.threads WHERE PROCESSLIST_COMMAND = 'Query' AND PROCESSLIST_TIME > 60; - 别信
INFO字段内容:有些客户端会截断 SQL,要用SHOW FULL PROCESSLIST(但注意权限,部分用户看不到)
临时止血:不重启也能降 CPU
很多 DBA 卡在“不敢 kill”,其实只要 kill 对了线程,CPU 会立刻回落:
- 优先 kill 掉
State = 'Sending data'且TIME > 60的线程 —— 它们通常在扫大表或做排序,持续消耗 CPU - 用
KILL QUERY [id](不是KILL [id])只中断当前语句,不干掉整个连接,避免应用层重连风暴 - 临时调小
innodb_buffer_pool_size反而可能恶化问题;但可以紧急增大tmp_table_size和max_heap_table_size(比如设为 512M),避免频繁落盘排序 - 如果发现是某个定时任务触发的批量更新,立刻在应用侧暂停该任务,而不是等它跑完
为什么刚优化过的 SQL 突然又烧 CPU?
生产环境最常被忽略的一点:MySQL 查询优化器依赖的统计信息可能已经严重过期,导致它选错执行计划。哪怕你加了索引,也可能被无视:
- 执行
ANALYZE TABLE your_table_name;强制刷新统计信息,再看EXPLAIN是否走索引 - 检查
information_schema.STATISTICS中的CARDINALITY值是否明显失真(比如主键列 cardinality = 1) - 如果表数据量近期增长 5 倍以上,
innodb_stats_auto_recalc默认是 ON,但有时会延迟触发 —— 别等它,手动ANALYZE - 注意:某些 ORM 框架生成的 SQL 带
SQL_NO_CACHE或动态拼接字段,会让 query cache 失效,同时增加解析开销,间接推高 CPU
真正难处理的不是单条慢 SQL,而是那些执行时间在 0.8~1.2 秒之间的“灰色查询”——它们进不了默认 long_query_time=1 的慢日志,却在高并发下把 CPU 推到临界点。上线前必须把 long_query_time 设成 0.5(浮点数,不能加引号),否则等于没开慢日志。


















