Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL CPU飙高排查

MySQL CPU飙高排查的全流程指南

作者:半桶水专家

当 MySQL 出现 CPU 持续飙高 时,问题往往不只存在于数据库本身,而可能涉及:SQL 执行效率,系统资源瓶颈以及并发模型等,本文提供一套 工程化三阶段排查方法,需要的朋友可以参考下

当 MySQL 出现 CPU 持续飙高 时,问题往往不只存在于数据库本身,而可能涉及:

本文提供一套 工程化三阶段排查方法

主机层定位 → 系统层分析 → MySQL 内部根因

目标是精准回答三个问题:

  1. CPU 被谁消耗?
  2. 为什么消耗?
  3. 如何优化?

第一阶段:确认问题范围(定位 CPU 消耗主体)

目标:明确 是谁在消耗 CPU

1.1 查看主机整体 CPU 负载

命令

top -c 

CPU 行解读

%Cpu(s): 10.4 us, 2.6 sy, 0.0 ni, 86.5 id, 0.1 wa, 0.0 hi, 0.4 si, 0.0 st 
字段含义判断
us用户态 CPU高 → SQL 计算密集
sy内核态 CPU高 → 系统调用频繁
waI/O 等待高 → 磁盘瓶颈
id空闲低 → CPU 真正繁忙

经验判断

Load Average 判断

load average: 8.2, 7.9, 6.5 

规则:

Load > CPU 核心数 = 系统过载

示例:

1.2 定位 MySQL 进程 PID

ps -ef | grep mysqld
# 或
pidof mysqld

记录 PID,例如:

12345 

1.3 查看 MySQL 内部线程 CPU(关键步骤)

MySQL = 多线程模型
一个连接 ≈ 一个线程。

top -H -p 12345 -d 1 

场景分析

✅ 场景 A:单线程 100%

含义:

单条慢 SQL

行动:

✅ 场景 B:大量线程均高

含义:

并发过高 / 连接风暴

行动:

✅ 场景 C:线程不高但整体 CPU 高

可能原因:

1.4 区分用户态与内核态 CPU

pidstat -p 12345 -u -h 1 5 
字段含义
%usrSQL 计算
%system内核消耗
%CPU总占用

第二阶段:系统层面排查

确认 mysqld 占 CPU 后,需要排除 操作系统导致的性能下降

2.1 上下文切换检查

vmstat 1 5 

重点字段:

字段含义
cs上下文切换
in中断次数

判断:

原因:

进一步:

pidstat -w -p 12345 1 5 

关注:

2.2 内存与 Swap 检查

free -m
vmstat 1 5

关键字段:

字段含义
siswap in
soswap out

⚠️ si/so != 0 = 严重问题

影响:

优化:

2.3 网络连接检查

netstat -an | grep ESTABLISHED | wc -l
netstat -an | grep TIME_WAIT | wc -l
ss -ant | grep :3306 | wc -l

判断:

现象含义
ESTABLISHED 高连接池失效
TIME_WAIT 高短连接风暴

优化:

2.4 磁盘 I/O 与 CPU 关联

iostat -x -k 1 5 

关注:

字段判断
%util接近100% = 饱和
await>10ms = 慢盘

若同时:

➡ CPU 是被动等待。

2.5 NUMA 架构检查

numactl --hardware
dmesg | grep -i numa

问题:

CPU 与内存跨节点访问

建议:

numactl --interleave=all /usr/sbin/mysqld 

2.6 硬中断检查

watch -n 1 'cat /proc/interrupts | grep -E "CPU|eth|nvme|sda"' 

如果某 CPU 中断暴涨:

➡ IRQ 未均衡

解决:

irqbalance 

第一、二阶段总结

检查项命令异常
CPUtopus/wa 高
线程top -H单线程100%
上下文vmstatcs 高
Swapvmstatsi/so>0
网络ssTIME_WAIT 多
NUMAnumactl未绑定

第三阶段:MySQL 层面排查(核心阶段)

当系统层无异常:

问题几乎一定在 SQL 或 MySQL 内部机制

3.1 实时会话分析(抓现行)

SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO
FROM information_schema.PROCESSLIST
WHERE COMMAND != 'Sleep'
ORDER BY TIME DESC
LIMIT 20;

STATE 含义

状态含义
Sending data全表扫描
Sorting result排序
Creating tmp table临时表
Waiting for lock锁竞争
PurgingUndo 清理

OS 线程关联(8.0)

通过:

performance_schema.threads 

关联:

3.2 慢查询分析(历史问题)

开启:

SET GLOBAL slow_query_log='ON';
SET GLOBAL long_query_time=0.1;
SET GLOBAL log_queries_not_using_indexes='ON';

mysqldumpslow

mysqldumpslow -s t -t 10 slow.log 

pt-query-digest(推荐)

pt-query-digest slow.log 

关注:

3.3 状态指标分析

线程

SHOW STATUS LIKE 'Threads_running'; 

规则:

Threads_running ≤ CPU 核心数

临时表

SHOW STATUS LIKE 'Created_tmp%'; 

磁盘临时表高 ⇒ SQL 或 tmp_table_size 问题。

Buffer Pool 命中率

计算:

1 - reads / read_requests 

目标:

≥ 99%

3.4 锁与事务分析

SHOW ENGINE INNODB STATUS\G 

关注:

大量 spin/wait ⇒ 锁竞争。

SELECT * FROM sys.innodb_lock_waits; 

检查:

3.5 执行计划分析(最终定位)

EXPLAIN FORMAT=JSON SELECT ...

关键字段:

字段危险信号
typeALL
keyNULL
rows极大
ExtraUsing filesort
ExtraUsing temporary

常见索引失效

  1. 违反最左前缀
  2. 函数计算
  3. 隐式类型转换
  4. %abc 模糊查询

3.6 Performance Schema 深度分析

SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT
FROM performance_schema.events_statements_summary_by_global_by_event_name
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;

实时:

SELECT *
FROM sys.session
ORDER BY current_statement_latency DESC;

第三阶段决策表

现象原因方案
单 SQL 慢全表扫描建索引
多 SQL 快并发高限流
tmp 表高排序调内存
Buffer miss内存小调 BP
锁等待长事务拆事务
Purging写入多调 purge

推荐排查顺序(实战经验)

① SHOW PROCESSLIST
        ↓
② Threads_running
        ↓
③ Slow Log
        ↓
④ EXPLAIN

以上就是MySQL CPU飙高排查的全流程指南的详细内容,更多关于MySQL CPU飙高排查的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文