三分鐘講透:MySQL CPU 500% 的排查與優(yōu)化套路
大家好呀,我是小米,31歲,坐標在一個天天和 MySQL 打交道的技術部,平時喜歡折騰技術,也喜歡把踩過的坑講成段子,分享給大家。
今天要聊的題目,是很多小伙伴在社招面試時可能被問到過的一個經典問題:
“如果 MySQL 數(shù)據庫 CPU 飆升到 500%,你會怎么處理?”
當時我第一次被問到這個問題的時候,腦子里第一反應是:“完蛋,這服務器怕不是要冒煙了吧!”但是冷靜下來想想,這類問題其實考察的并不是你背答案,而是你有沒有處理線上問題的思路和能力。
那今天,就讓我給大家拆解一下這個問題,同時用一個小故事的方式,把我在真實項目里踩過的坑分享給你們。
1.故事開場:凌晨兩點的報警電話
事情發(fā)生在去年的某個深夜。
那天我剛準備進入美夢,突然手機叮的一聲,一條報警短信彈出來:
告警:MySQL CPU 使用率 500%,請立即處理!
我整個人瞬間清醒。500%是個什么概念?我們機器是 8 核的,500% 就是 5 核被壓榨得死死的,服務器分分鐘可能宕機。
于是我立刻披上外套,打開電腦遠程登錄服務器。接下來,就是一場和“CPU 飆升”的較量。
2.第一步:到底是不是 MySQL 的鍋?
當遇到 CPU 飆升時,第一件事不是慌,而是要先定位元兇。
我敲下了熟悉的命令:

果然,mysqld 進程赫然在列,占用了絕大多數(shù) CPU。
這一步很關鍵!因為很多人一上來就覺得一定是數(shù)據庫的鍋,其實有時候可能是別的進程(比如日志進程、惡意腳本)搶資源。
所以總結一下第一步:
- 先用 top 等操作系統(tǒng)命令,確認是不是 mysqld 占用導致的。
- 如果不是,那就去追查別的進程。
- 如果是,那就進入下一步
3.第二步:誰在數(shù)據庫里搗亂?
既然是 MySQL 占用過高,那接下來要看看:是哪個 SQL 把 CPU 吃爆了。
這時候經典命令登場:
圖片
屏幕上立刻刷出了幾十條正在運行的 session。果然,有幾個 SQL 正在跑,而且狀態(tài)卡在 Sending data 上,執(zhí)行了十幾秒還沒結束。
這就是罪魁禍首了。
那么該怎么辦呢?
- 先確認 SQL 是誰的:比如是哪個應用、哪個功能觸發(fā)的。
- 分析 SQL 是否有問題:比如寫得不合理、沒用上索引。
- 檢查數(shù)據量:有時候 SQL 沒錯,但是單表太大,掃描量太多,也會吃 CPU。
我當時就是先挑出幾個明顯異常的 session,果斷執(zhí)行:
圖片
CPU 使用率果然立刻從 500% 掉到 200% 左右。這一刀下去,算是止血了,但問題還沒真正解決。
4.第三步:SQL 優(yōu)化與索引
止血之后,我開始分析那幾個消耗高的 SQL。
拿其中一條來說,大概長這樣:
圖片
聽起來沒啥毛病對吧?但是當我一看執(zhí)行計劃,發(fā)現(xiàn)它居然在全表掃描!原因是 status != 'CLOSED' 這種寫法,讓索引徹底失效了。
于是我立刻和同事溝通,把 SQL 改成:
圖片
同時在 customer_id, status 上建了一個聯(lián)合索引。優(yōu)化后的 SQL 再跑,瞬間就從幾十秒降到毫秒級。
那一刻我心里只想說:
索引就是數(shù)據庫的靈魂,寫 SQL 時不考慮索引,就等著 CPU 飆升吧。
5.第四步:別忘了連接數(shù)的陷阱
不過,CPU 飆升并不一定都是“某幾條 SQL”造成的。
有一次,我遇到的情況是:
每條 SQL 都很正常,執(zhí)行時間很短,但 CPU 一樣沖到 400%-500%。
后來一查,原來是因為應用層突然有個 bug,瘋狂建立數(shù)據庫連接,短時間內涌入了幾百個 session。
這種場景下,你 kill 再多線程也沒用,因為新的連接會源源不斷涌進來。
解決辦法就不一樣了:
- 限制數(shù)據庫最大連接數(shù),防止被沖垮。
- 檢查應用層邏輯,為什么會短時間內有這么多連接?是重試機制問題?還是連接池沒配置好?
我記得那次,我們在 MySQL 配置里調整了 max_connections,同時應用端修復了連接池的 bug,CPU 才徹底恢復穩(wěn)定。
6.總結經驗:處理 CPU 飆升的黃金流程
到這里,我已經把兩個最典型的場景講完了。那我們不妨把思路梳理成一個面試時能用的黃金流程:
1)確認 CPU 占用元兇
- 用 top 等命令確認是不是 mysqld 占用。
2)查看數(shù)據庫當前線程
- 用 show processlist 找出消耗資源的 SQL。
3)SQL 優(yōu)化與索引調整
- 檢查執(zhí)行計劃,優(yōu)化寫法,補充索引。
4)必要時立即止血
- kill 高消耗線程,觀察 CPU 是否下降。
5)排查并發(fā)連接問題
- 如果是大量 session 導致,就要限制連接數(shù),修復應用邏輯。
6)長期方案
- 調整內存參數(shù)、優(yōu)化表結構、做分庫分表,甚至引入緩存。
圖片
7.面試答題套路
如果你在面試中被問到這個問題,可以用這樣的思路來回答:
“當 MySQL CPU 飆升時,我會先用操作系統(tǒng)命令確認是不是數(shù)據庫導致的,如果不是則排查其他進程。如果是 MySQL 的問題,會通過 show processlist 查看正在運行的 session,找出是否有大 SQL 或者執(zhí)行異常的 SQL。如果有高消耗 SQL,會先 kill 線程止血,再分析執(zhí)行計劃,看是否缺少索引、SQL 寫法是否合理。如果不是單條 SQL 消耗過高,而是連接數(shù)暴增導致的,我會和應用側排查為何會有這么多連接,同時通過限制連接數(shù)來緩解壓力。最后再根據情況做持久優(yōu)化,比如加索引、改 SQL、調參數(shù)。”
這樣一套邏輯下來,面試官肯定會覺得你對線上問題的處理有條理。
8.彩蛋:小米的踩坑教訓
最后給大家分享一個小插曲:
我第一次遇到 CPU 飆升時,沒想太多,直接一通亂 kill,把好幾個正常業(yè)務的 SQL 也殺了,結果引發(fā)了線上小故障,被領導批評了一頓。
所以后來我學會了一個原則:
先觀察,后下手;先止血,后優(yōu)化。
殺線程只是臨時措施,真正的解決方案永遠是優(yōu)化 SQL 和系統(tǒng)架構。
9.結語
好了,今天的分享就到這里啦。
如果你正在準備 Java 社招面試,這道題一定要爛熟于心,因為它不光考數(shù)據庫功底,還考察你遇事冷靜、思路清晰的能力。
希望大家下次被問到:“MySQL CPU 飆升到 500%怎么辦?”,都能胸有成竹地答出來,不再心慌。





























