mysqlCPU占用过高怎么办_mysql资源异常排查

来源:这里教程网 时间:2026-02-28 20:42:02 作者:

查出哪些 SQL 正在吃 CPU

MySQL 本身不直接暴露“CPU 占用”到每个查询,但高 CPU 往往对应大量执行、全表扫描、锁等待或排序/分组操作。优先看

SHOW PROCESSLIST
information_schema.PROCESSLIST
,筛选
Command
Query
Time
较长的线程:

SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO 
FROM information_schema.PROCESSLIST 
WHERE COMMAND = 'Query' AND TIME > 10 
ORDER BY TIME DESC LIMIT 10;

注意:

INFO
列可能被截断,可搭配
SHOW FULL PROCESSLIST
(需有
PROCESS
权限);若看到大量
Copying to tmp table
Sorting result
Sending data
状态,基本就是 CPU 或内存瓶颈点。

检查慢查询和执行计划

开启并分析

slow_query_log
是最直接的方式。确认是否已启用:

SHOW VARIABLES LIKE 'slow_query_log';

若关闭,临时启用(重启不丢失需写入配置文件):

SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;  -- 记录超过 1 秒的查询

然后查日志路径:

SHOW VARIABLES LIKE 'slow_query_log_file';

拿到慢 SQL 后,用

EXPLAIN
看执行计划,重点关注:

type
ALL
(全表扫描)或
index
(全索引扫描)
rows
预估扫描行数远超实际返回行数
Extra
出现
Using filesort
Using temporary

这类语句极易推高 CPU —— 尤其当

ORDER BY
GROUP BY
没走索引时。

识别隐式类型转换和函数索引失效

这类问题不会报错,但会让索引完全失效,导致本该毫秒级的查询变成全表扫描。典型例子:

SELECT * FROM users WHERE mobile = 13800138000;  -- mobile 是 VARCHAR,却传了数字

MySQL 会把每行

mobile
转成数字再比对,索引失效。同理:

SELECT * FROM orders WHERE DATE(create_time) = '2024-01-01';  -- DATE() 函数使 create_time 索引失效

应改写为:

SELECT * FROM orders WHERE create_time >= '2024-01-01' AND create_time < '2024-01-02';

其他常见陷阱包括:

LIKE '%abc'
(左模糊)、
OR
连接非同索引字段、对索引字段做运算(如
WHERE id + 1 = 100
)。

临时降载和连接数控制

如果 CPU 已飙到 95%+ 且业务卡死,先止损再排查:

KILL
干掉明确的坏查询(如上面查出的长时间
Query
):
KILL 12345;
限制新连接:设
max_connections
临时降低(如从 500 改为 100),避免雪崩:
SET GLOBAL max_connections = 100;
关掉非关键功能:比如停掉监控采集、报表导出等定时任务 确认没有应用端连接泄漏 —— 查
Threads_connected
是否持续增长却不释放

这些是应急手段,不能替代根因优化。真正麻烦的往往是那些“单条不慢、但并发一高就 CPU 爆表”的查询 —— 它们往往缺少合适的复合索引,或事务持有锁时间过长。

相关推荐