先确认mysqld是否真占CPU,用top按P排序;若确认,则查%sy、cs、wa指标,再用SELECT从PROCESSLIST抓活跃SQL,重点关注Sending data、Sorting result等state,结合innodb_status和统计信息过期情况综合判断。

先确认是不是 mysqld 进程真正在吃 CPU
别急着进 MySQL,top 命令是第一道过滤网。执行 top,按 Shift+P 按 CPU 使用率排序,看排第一的是否是 mysqld。如果不是,比如是 java、python 或某个 backup 脚本,那问题根本不在数据库——杀错进程只会让业务更糟。
如果确认是 mysqld,再补看三组关键指标:
-
%sy(内核态 CPU)异常高 → 往往是锁争用或大量线程切换,不是 SQL 本身慢 -
cs(context switch)超过 10k/s → 线程调度压力大,常见于连接暴增或thread_cache_size设置过小 -
wa(I/O wait)很低但 CPU 高 → 排除磁盘瓶颈,基本锁定为计算密集型操作(如大表排序、无索引 join)
快速抓出正在“烧 CPU”的活跃 SQL
SHOW PROCESSLIST 默认只返回前 100 行,且 INFO 字段常被截断。真正有效的命令是:
SELECT id, user, host, db, command, time, state, LEFT(info, 500) AS sql_text FROM information_schema.PROCESSLIST WHERE command != 'Sleep' AND info IS NOT NULL ORDER BY time DESC LIMIT 20;
重点关注这几类 state:
-
Sending data:通常在扫描大表或传输结果集,没走索引或结果集太大 -
Sorting result或Creating sort index:ORDER BY/GROUP BY引发内存排序,可能触发磁盘临时表 -
Locked或Waiting for table metadata lock:不是 SQL 慢,是有人 hold 住了 DDL 锁(比如正在ALTER TABLE),其他查询全卡住
注意:TIME 列大于 60 秒的线程,优先 kill;用 KILL QUERY [id] 中断语句,别用 KILL [id] 干掉整个连接,否则应用重连风暴会让 CPU 更高。
查完活跃线程后,必须看 innodb_status 和统计信息
执行 SHOW ENGINE INNODB STATUS\G,重点翻到 TRANSACTIONS 和 SEMAPHORES 部分:
- 如果
---TRANSACTION下有大量TRX HAS BEEN WAITING记录 → 锁等待堆积,得结合performance_schema.data_locks找阻塞源头 - 如果
SEMAPHORES里os_waits数值极高(比如每秒几百次)→ 内核态竞争严重,可能是innodb_thread_concurrency设置不当或 buffer pool 分区不足
再顺手检查统计信息是否过期:
SELECT table_schema, table_name, update_time
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema')
AND update_time < NOW() - INTERVAL 7 DAY;MySQL 5.7 的优化器严重依赖统计信息。如果大表的统计信息几个月没更新,EXPLAIN 显示的 rows 可能差几个数量级,导致选错执行计划,CPU 直接拉满。
别忽略 sleep 连接和配置项的隐性影响
大量 Command = Sleep 且 Time 很长的连接,不是“没事干”,而是应用没正确释放连接。它们持续占用线程资源,推高 Threads_connected,间接加剧上下文切换(cs)。
紧急可调的两个参数(无需重启):
-
SET GLOBAL wait_timeout = 30;:让空闲连接更快释放(注意应用层连接池需同步调整) -
SET GLOBAL tmp_table_size = 268435456;和SET GLOBAL max_heap_table_size = 268435456;:避免小排序/分组被迫写磁盘临时表,减少 CPU + IO 双开销
真正容易被忽略的是 innodb_buffer_pool_instances。MySQL 5.7 默认是 8,但如果 buffer pool 总大小超过 4G,建议设为 16 或 32——否则单个 buffer pool mutex 成为热点,所有线程排队等锁,%sy 就会飙升。


















