最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL數(shù)據(jù)庫CPU飆升到500%的原因和解決方案

 更新時間:2026年02月27日 09:09:49   作者:嘻哈baby  
這篇文章討論了MySQL?CPU使用率高達500%的問題,并提出了滅火、查因、防復發(fā)的處理步驟,滅火包括找到并終止問題SQL,查因涉及分析全表掃描、鎖等待和排序等,防復發(fā)則包括優(yōu)化索引、限制連接數(shù)、應(yīng)用層限流和緩存等措施,需要的朋友可以參考下

CPU 500%意味著MySQL吃掉了好幾個核,基本上是某些SQL在瘋狂消耗計算資源。這種情況下不要急著重啟——重啟只是把問題藏起來了,過一會兒還會炸。

先滅火,再查因,最后防復發(fā)。按這個順序來。

滅火:先找到罪魁禍首

登上服務(wù)器,第一件事不是看MySQL,是看操作系統(tǒng)。

top -Hp $(pidof mysqld)

這條命令列出mysqld進程下所有線程的CPU占用。找到CPU最高的那幾個線程,記下它們的LWP(輕量級進程ID)。

然后進MySQL:

SHOW PROCESSLIST;

或者更詳細的版本:

SELECT id, user, host, db, command, time, state, info 
FROM information_schema.processlist 
WHERE command != 'Sleep' 
ORDER BY time DESC;

重點看 command 不是Sleep的連接——Sleep的連接是空閑的,不吃CPU???time 列,跑了幾百秒甚至幾千秒的查詢大概率就是兇手。info 列顯示正在執(zhí)行的SQL。

找到了問題SQL之后,如果業(yè)務(wù)允許,直接殺掉:

KILL <process_id>;

這一步的目的是止血。CPU降下來之后,你才有余裕去分析根因。如果不先殺掉問題查詢,服務(wù)器可能連登錄都卡。

查因:為什么這條SQL吃這么多CPU

CPU飆升的原因,90%以上是這幾種情況。

全表掃描。 一條查詢沒走索引,掃了幾百萬行甚至幾千萬行。每一行都要從磁盤讀到內(nèi)存(如果Buffer Pool裝不下的話),然后逐行比較WHERE條件。CPU的消耗主要在"逐行比較"這一步。

拿到問題SQL之后,用EXPLAIN看一下:

EXPLAIN SELECT ... ;

如果 type 列是 ALL,rows 列是幾百萬,那就是全表掃描???key 列是不是NULL——NULL說明沒用上任何索引。

鎖等待引發(fā)的連鎖反應(yīng)。 一條慢SQL持有行鎖,后面的請求全部排隊等鎖。等待的連接越來越多,每個連接都占一個線程,MySQL的線程調(diào)度開銷就上去了。這種情況下CPU高不是因為在"計算",而是因為在"調(diào)度"。

SELECT * FROM information_schema.innodb_trx 
ORDER BY trx_started ASC;

這條命令列出所有活躍事務(wù),按開始時間排序。跑了最久的那個事務(wù)大概率是罪魁禍首——它持有鎖不釋放,后面的事務(wù)全部堵住了。

SELECT * FROM performance_schema.data_lock_waits;

這條(MySQL 8.0+)能看到誰在等誰的鎖。如果 BLOCKING_ENGINE_TRANSACTION_ID 指向的事務(wù)已經(jīng)跑了很久,考慮殺掉它。

排序和臨時表。ORDER BYGROUP BY 的查詢,如果排序字段沒有索引,MySQL會在內(nèi)存里(或者磁盤上)建臨時表做排序。數(shù)據(jù)量一大,排序本身就是CPU密集型操作。

EXPLAIN里看到 Extra 列有 Using filesortUsing temporary,就是這個情況。

大量短連接。 某些應(yīng)用沒用連接池,每次請求都新建MySQL連接、用完就斷開。MySQL創(chuàng)建和銷毀連接的開銷不?。ㄒ稣J證、分配線程、初始化會話變量)。如果QPS很高,光是連接管理就能把CPU吃滿。

SHOW GLOBAL STATUS LIKE 'Threads_created';
SHOW GLOBAL STATUS LIKE 'Connections';

如果 Threads_created 的值很高且在快速增長,說明在頻繁創(chuàng)建新線程。正常情況下,連接池會復用線程,Threads_created 應(yīng)該增長很慢。

常見場景的具體處理

場景一:某條慢SQL導致CPU飆升

這是最常見的情況。處理步驟:

殺掉問題查詢 → EXPLAIN分析 → 加索引或改寫SQL → 驗證。

加索引的時候注意:在生產(chǎn)環(huán)境給大表加索引,MySQL 5.6之前會鎖表,5.6之后支持Online DDL,但仍然會消耗大量IO。如果表有幾千萬行,加索引可能要跑幾分鐘到幾十分鐘,期間會影響寫入性能。

建議在業(yè)務(wù)低峰期操作,或者用 pt-online-schema-change 工具:

pt-online-schema-change --alter "ADD INDEX idx_user_status(user_id, status)" \
  D=mydb,t=orders --execute

這個工具的原理是創(chuàng)建一張新表、加上索引、通過觸發(fā)器同步數(shù)據(jù)、最后原子性地rename。對線上業(yè)務(wù)的影響比直接ALTER TABLE小很多。

場景二:大事務(wù)持有鎖導致連鎖堵塞

SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query
FROM information_schema.innodb_trx
WHERE trx_started < NOW() - INTERVAL 60 SECOND;

找到跑了超過60秒的事務(wù),看它在干什么。如果是一個忘記提交的事務(wù)(trx_query 為NULL說明當前沒在執(zhí)行SQL,但事務(wù)還開著),直接殺掉對應(yīng)的連接:

KILL <trx_mysql_thread_id>;

然后去排查應(yīng)用代碼——大概率是某個地方開了事務(wù)忘記commit/rollback,或者事務(wù)里做了不該做的事(比如在事務(wù)里調(diào)了外部HTTP接口,接口超時導致事務(wù)一直掛著)。

場景三:突發(fā)流量導致CPU飆升

不是某條SQL有問題,而是正常的SQL突然來了十倍的量。這種情況加索引沒用,因為每條SQL本身都很快,只是量太大了。

短期應(yīng)對:

SET GLOBAL max_connections = 500;

限制最大連接數(shù),超出的請求直接拒絕,保護MySQL不被打死。比讓所有請求都卡住要好——至少一部分請求能正常處理。

中期方案:應(yīng)用層加限流、加緩存。把熱點查詢的結(jié)果緩存到Redis,大部分請求不打到MySQL。

長期方案:讀寫分離,讀請求分散到從庫。

預防:別等CPU飆了再處理

開慢查詢?nèi)罩尽?/strong> 這是最基本的。

SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;

long_query_time 設(shè)成1秒。很多人設(shè)成10秒,那等于只能抓到"已經(jīng)嚴重影響用戶體驗"的查詢。1秒的閾值能讓你提前發(fā)現(xiàn)潛在問題。

監(jiān)控線程狀態(tài)。 定期檢查活躍連接數(shù)和長時間運行的查詢:

SELECT COUNT(*) FROM information_schema.processlist WHERE command != 'Sleep';

活躍連接數(shù)突然飆升,往往是CPU飆升的前兆。配合Prometheus + Grafana做監(jiān)控告警,活躍連接超過閾值就報警。

定期審查慢查詢。 每周跑一次 pt-query-digest,看看有沒有新出現(xiàn)的慢查詢。很多CPU飆升事故不是突然發(fā)生的,而是某條SQL隨著數(shù)據(jù)量增長越來越慢,從100ms慢到1秒,從1秒慢到10秒,最后某天數(shù)據(jù)量過了臨界點,直接把CPU打滿。

檢查Buffer Pool命中率。

SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';

Innodb_buffer_pool_read_requests(邏輯讀)和 Innodb_buffer_pool_reads(物理讀,即磁盤讀)算 命中率:1 - 物理讀/邏輯讀。正常應(yīng)該在99%以上。如果低于95%,說明Buffer Pool太小,大量數(shù)據(jù)要從磁盤讀,CPU花在IO等待上的時間就多了。調(diào)大 innodb_buffer_pool_size,一般設(shè)成物理內(nèi)存的60%-80%。

一個容易忽略的點

MySQL的CPU飆升有時候不是MySQL本身的問題。

檢查一下服務(wù)器上是不是還跑著別的東西——有些運維圖省事,把應(yīng)用服務(wù)和MySQL部署在同一臺機器上。應(yīng)用服務(wù)突然吃了大量CPU,MySQL分到的CPU時間片就少了,本來100ms能跑完的查詢變成了500ms,連接堆積,惡性循環(huán)。

top 命令看一眼整體CPU分布,如果mysqld不是CPU占用最高的進程,那問題可能根本不在MySQL。

還有一種情況是OOM Killer。Linux內(nèi)核在內(nèi)存不足的時候會殺掉占內(nèi)存最多的進程,MySQL經(jīng)常是第一個被殺的。殺完之后MySQL重啟,Buffer Pool是冷的,所有查詢都要從磁盤讀數(shù)據(jù),CPU和IO同時飆升。看 dmesg | grep -i oom 能確認是不是被OOM Killer干掉過。

線上數(shù)據(jù)庫出問題的時候,最重要的不是你知道多少優(yōu)化技巧,而是能不能在壓力下保持冷靜、按步驟排查。先止血、再查因、最后防復發(fā)——這三步的順序不能亂。CPU飆到500%的時候最怕的操作就是慌了直接重啟,重啟完發(fā)現(xiàn)問題還在,又開始亂改配置,越改越亂。

以上就是MySQL數(shù)據(jù)庫CPU飆升到500%的原因和解決方案的詳細內(nèi)容,更多關(guān)于MySQL CPU飆升到500%的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

盖州市| 洛扎县| 那坡县| 寿阳县| 新安县| 禹城市| 甘泉县| 灵寿县| 保德县| 海丰县| 梁平县| 成都市| 岑溪市| 大埔县| 南漳县| 高陵县| 叙永县| 浮梁县| 五大连池市| 建水县| 夹江县| 桦南县| 曲周县| 曲水县| 红安县| 鹿泉市| 拉萨市| 云浮市| 积石山| 巴中市| 敦煌市| 兴山县| 察隅县| 开化县| 三河市| 綦江县| 张家港市| 锡林郭勒盟| 邛崃市| 唐山市| 兴化市|