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

9次阅读

优先查 PROCEsslIST 中 TIME>10 且 STATE 为 Copying to tmp table/Sending data 的查询;再启用 slow_query_log 并用 EXPLaiN 分析全表扫描、using filesort 等高 CPU 操作;最后排查隐式类型转换和函数导致的索引失效。

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

查出哪些 sql 正在吃 CPU

mysql 本身不直接暴露“CPU 占用”到每个查询,但高 CPU 往往对应大量执行、全表扫描、锁等待或排序/分组操作。优先看 SHOW PROCESSLISTinformation_schema.PROCESSLIST,筛选 CommandQueryTime 较长的线程

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 tableSorting resultSending 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 看执行计划,重点关注:

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

这类语句极易推高 CPU —— 尤其当 ORDER BYGROUP 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 爆表”的查询 —— 它们往往缺少合适的复合索引,或事务持有锁时间过长。

text=ZqhQzanResources