当 MySQL 出现 CPU 持续飙高 时,问题往往不只存在于数据库本身,而可能涉及:
SQL 执行效率系统资源瓶颈并发模型内核调度I/O 或网络行为本文提供一套 工程化三阶段排查方法:
主机层定位 → 系统层分析 → MySQL 内部根因
目标是精准回答三个问题:
- CPU 被谁消耗?为什么消耗?如何优化?
第一阶段:确认问题范围(定位 CPU 消耗主体)
目标:明确 是谁在消耗 CPU。
MySQL 整体?单个线程?SQL 计算?内核系统调用?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 真正繁忙
经验判断
us > 70% → SQL 问题概率极高sy 高 → 锁 / 内核调度问题wa 高 → I/O 伪 CPU 高
Load Average 判断
load average: 8.2, 7.9, 6.5
规则:
Load > CPU 核心数 = 系统过载
示例:
4 核 CPUload = 8➡ 存在运行队列堆积
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
行动:
记录线程 ID去 MySQL 查 SQL✅ 场景 B:大量线程均高
含义:
并发过高 / 连接风暴
行动:
检查连接池限制最大连接✅ 场景 C:线程不高但整体 CPU 高
可能原因:
MySQL 后台线程锁竞争上下文切换1.4 区分用户态与内核态 CPU
pidstat -p 12345 -u -h 1 5
字段 含义 %usrSQL 计算%system内核消耗%CPU总占用
第二阶段:系统层面排查
确认 mysqld 占 CPU 后,需要排除 操作系统导致的性能下降。
2.1 上下文切换检查
vmstat 1 5
重点字段:
判断:
正常:几千/s异常:> 20000/s原因:
线程过多锁竞争CPU 抢占进一步:
pidstat -w -p 12345 1 5
关注:
cswch/snvcswch/s
2.2 内存与 Swap 检查
free -m vmstat 1 5
关键字段:
⚠️ si/so != 0 = 严重问题
影响:
CPU sy 飙升数据库性能断崖下降优化:
增内存调整 buffer poolswapoff -a
2.3 网络连接检查
netstat -an | grep ESTABLISHED | wc -l netstat -an | grep TIME_WAIT | wc -l ss -ant | grep :3306 | wc -l
判断:
优化:
使用连接池tcp_tw_reuse2.4 磁盘 I/O 与 CPU 关联
iostat -x -k 1 5
关注:
若同时:
wa 高%util 高
➡ 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
第一、二阶段总结
第三阶段: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 含义
OS 线程关联(8.0)
通过:
performance_schema.threads
关联:
PROCESSLIST_IDTHREAD_OS_ID3.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
关注:
Rows examineResponse time3.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
关注:
TRANSACTIONSSEMAPHORES大量 spin/wait ⇒ 锁竞争。
SELECT * FROM sys.innodb_lock_waits;
检查:
长事务DDL 阻塞3.5 执行计划分析(最终定位)
EXPLAIN FORMAT=JSON SELECT ...
关键字段:
常见索引失效
- 违反最左前缀函数计算隐式类型转换
%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;
第三阶段决策表
推荐排查顺序(实战经验)
① SHOW PROCESSLIST ↓ ② Threads_running ↓ ③ Slow Log ↓ ④ EXPLAIN
以上就是MySQL CPU飙高排查的全流程指南的详细内容,更多关于MySQL CPU飙高排查的资料请关注其它相关文章!
