MySQL CPU飆高排查的全流程指南
當(dāng) MySQL 出現(xiàn) CPU 持續(xù)飆高 時(shí),問題往往不只存在于數(shù)據(jù)庫本身,而可能涉及:
- SQL 執(zhí)行效率
- 系統(tǒng)資源瓶頸
- 并發(fā)模型
- 內(nèi)核調(diào)度
- I/O 或網(wǎng)絡(luò)行為
本文提供一套 工程化三階段排查方法:
主機(jī)層定位 → 系統(tǒng)層分析 → MySQL 內(nèi)部根因
目標(biāo)是精準(zhǔn)回答三個(gè)問題:
- CPU 被誰消耗?
- 為什么消耗?
- 如何優(yōu)化?
第一階段:確認(rèn)問題范圍(定位 CPU 消耗主體)
目標(biāo):明確 是誰在消耗 CPU。
- MySQL 整體?
- 單個(gè)線程?
- SQL 計(jì)算?
- 內(nèi)核系統(tǒng)調(diào)用?
1.1 查看主機(jī)整體 CPU 負(fù)載
命令
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 | 用戶態(tài) CPU | 高 → SQL 計(jì)算密集 |
| sy | 內(nèi)核態(tài) CPU | 高 → 系統(tǒng)調(diào)用頻繁 |
| wa | I/O 等待 | 高 → 磁盤瓶頸 |
| id | 空閑 | 低 → CPU 真正繁忙 |
經(jīng)驗(yàn)判斷
us > 70%→ SQL 問題概率極高sy 高→ 鎖 / 內(nèi)核調(diào)度問題wa 高→ I/O 偽 CPU 高
Load Average 判斷
load average: 8.2, 7.9, 6.5
規(guī)則:
Load > CPU 核心數(shù) = 系統(tǒng)過載
示例:
- 4 核 CPU
- load = 8
? 存在運(yùn)行隊(duì)列堆積
1.2 定位 MySQL 進(jìn)程 PID
ps -ef | grep mysqld # 或 pidof mysqld
記錄 PID,例如:
12345
1.3 查看 MySQL 內(nèi)部線程 CPU(關(guān)鍵步驟)
MySQL = 多線程模型
一個(gè)連接 ≈ 一個(gè)線程。
top -H -p 12345 -d 1
場景分析
? 場景 A:單線程 100%
含義:
單條慢 SQL
行動(dòng):
- 記錄線程 ID
- 去 MySQL 查 SQL
? 場景 B:大量線程均高
含義:
并發(fā)過高 / 連接風(fēng)暴
行動(dòng):
- 檢查連接池
- 限制最大連接
? 場景 C:線程不高但整體 CPU 高
可能原因:
- MySQL 后臺(tái)線程
- 鎖競爭
- 上下文切換
1.4 區(qū)分用戶態(tài)與內(nèi)核態(tài) CPU
pidstat -p 12345 -u -h 1 5
| 字段 | 含義 |
|---|---|
| %usr | SQL 計(jì)算 |
| %system | 內(nèi)核消耗 |
| %CPU | 總占用 |
第二階段:系統(tǒng)層面排查
確認(rèn) mysqld 占 CPU 后,需要排除 操作系統(tǒng)導(dǎo)致的性能下降。
2.1 上下文切換檢查
vmstat 1 5
重點(diǎn)字段:
| 字段 | 含義 |
|---|---|
| cs | 上下文切換 |
| in | 中斷次數(shù) |
判斷:
- 正常:幾千/s
- 異常:> 20000/s
原因:
- 線程過多
- 鎖競爭
- CPU 搶占
進(jìn)一步:
pidstat -w -p 12345 1 5
關(guān)注:
cswch/snvcswch/s
2.2 內(nèi)存與 Swap 檢查
free -m vmstat 1 5
關(guān)鍵字段:
| 字段 | 含義 |
|---|---|
| si | swap in |
| so | swap out |
?? si/so != 0 = 嚴(yán)重問題
影響:
- CPU sy 飆升
- 數(shù)據(jù)庫性能斷崖下降
優(yōu)化:
- 增內(nèi)存
- 調(diào)整 buffer pool
swapoff -a
2.3 網(wǎng)絡(luò)連接檢查
netstat -an | grep ESTABLISHED | wc -l netstat -an | grep TIME_WAIT | wc -l ss -ant | grep :3306 | wc -l
判斷:
| 現(xiàn)象 | 含義 |
|---|---|
| ESTABLISHED 高 | 連接池失效 |
| TIME_WAIT 高 | 短連接風(fēng)暴 |
優(yōu)化:
- 使用連接池
- tcp_tw_reuse
2.4 磁盤 I/O 與 CPU 關(guān)聯(lián)
iostat -x -k 1 5
關(guān)注:
| 字段 | 判斷 |
|---|---|
| %util | 接近100% = 飽和 |
| await | >10ms = 慢盤 |
若同時(shí):
wa 高%util 高
? CPU 是被動(dòng)等待。
2.5 NUMA 架構(gòu)檢查
numactl --hardware dmesg | grep -i numa
問題:
CPU 與內(nèi)存跨節(jié)點(diǎn)訪問
建議:
numactl --interleave=all /usr/sbin/mysqld
2.6 硬中斷檢查
watch -n 1 'cat /proc/interrupts | grep -E "CPU|eth|nvme|sda"'
如果某 CPU 中斷暴漲:
? IRQ 未均衡
解決:
irqbalance
第一、二階段總結(jié)
| 檢查項(xiàng) | 命令 | 異常 |
|---|---|---|
| CPU | top | us/wa 高 |
| 線程 | top -H | 單線程100% |
| 上下文 | vmstat | cs 高 |
| Swap | vmstat | si/so>0 |
| 網(wǎng)絡(luò) | ss | TIME_WAIT 多 |
| NUMA | numactl | 未綁定 |
第三階段:MySQL 層面排查(核心階段)
當(dāng)系統(tǒng)層無異常:
問題幾乎一定在 SQL 或 MySQL 內(nèi)部機(jī)制
3.1 實(shí)時(shí)會(huì)話分析(抓現(xiàn)行)
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' ORDER BY TIME DESC LIMIT 20;
STATE 含義
| 狀態(tài) | 含義 |
|---|---|
| Sending data | 全表掃描 |
| Sorting result | 排序 |
| Creating tmp table | 臨時(shí)表 |
| Waiting for lock | 鎖競爭 |
| Purging | Undo 清理 |
OS 線程關(guān)聯(lián)(8.0)
通過:
performance_schema.threads
關(guān)聯(lián):
- PROCESSLIST_ID
- THREAD_OS_ID
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
關(guān)注:
- Rows examine
- Response time
3.3 狀態(tài)指標(biāo)分析
線程
SHOW STATUS LIKE 'Threads_running';
規(guī)則:
Threads_running ≤ CPU 核心數(shù)
臨時(shí)表
SHOW STATUS LIKE 'Created_tmp%';
磁盤臨時(shí)表高 ⇒ SQL 或 tmp_table_size 問題。
Buffer Pool 命中率
計(jì)算:
1 - reads / read_requests
目標(biāo):
≥ 99%
3.4 鎖與事務(wù)分析
SHOW ENGINE INNODB STATUS\G
關(guān)注:
- TRANSACTIONS
- SEMAPHORES
大量 spin/wait ⇒ 鎖競爭。
SELECT * FROM sys.innodb_lock_waits;
檢查:
- 長事務(wù)
- DDL 阻塞
3.5 執(zhí)行計(jì)劃分析(最終定位)
EXPLAIN FORMAT=JSON SELECT ...
關(guān)鍵字段:
| 字段 | 危險(xiǎn)信號(hào) |
|---|---|
| type | ALL |
| key | NULL |
| rows | 極大 |
| Extra | Using filesort |
| Extra | Using temporary |
常見索引失效
- 違反最左前綴
- 函數(shù)計(jì)算
- 隱式類型轉(zhuǎn)換
%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;
實(shí)時(shí):
SELECT * FROM sys.session ORDER BY current_statement_latency DESC;
第三階段決策表
| 現(xiàn)象 | 原因 | 方案 |
|---|---|---|
| 單 SQL 慢 | 全表掃描 | 建索引 |
| 多 SQL 快 | 并發(fā)高 | 限流 |
| tmp 表高 | 排序 | 調(diào)內(nèi)存 |
| Buffer miss | 內(nèi)存小 | 調(diào) BP |
| 鎖等待 | 長事務(wù) | 拆事務(wù) |
| Purging | 寫入多 | 調(diào) purge |
推薦排查順序(實(shí)戰(zhàn)經(jīng)驗(yàn))
① SHOW PROCESSLIST
↓
② Threads_running
↓
③ Slow Log
↓
④ EXPLAIN以上就是MySQL CPU飆高排查的全流程指南的詳細(xì)內(nèi)容,更多關(guān)于MySQL CPU飆高排查的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
mysql中 ${param}與#{param}使用區(qū)別
這篇文章主要介紹了mysql中 ${param}與#{param}使用區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
MySQL連接時(shí)出現(xiàn)2003錯(cuò)誤的實(shí)現(xiàn)
本文主要介紹了MySQL連接時(shí)出現(xiàn)2003錯(cuò)誤的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
MySQL null與not null和null與空值''''''''的區(qū)別詳解
mysql優(yōu)化limit查詢語句的5個(gè)方法

