-
1 # 恍若不知
-
2 # jimware
mysql資料庫導致cpu過高一般從執行狀態分析:
執行狀態分析
Sleep狀態
通常代表資源未釋放,如果是透過連線池,sleep狀態應該恆定在一定數量範圍內
實戰範例:因前端資料輸出時(特別是輸出到使用者終端)未及時關閉資料庫連線,導致因網路連線速度產生大量sleep連線,在網速出現異常時,資料庫too many connections掛死。
簡單解讀,資料查詢和執行通常只需要不到0.01秒,而網路輸出通常需要1秒左右甚至更長,原本資料連線在0.01秒即可釋放,但是因為前端程式未執行close操作,直接輸出結果,那麼在結果未展現在使用者桌面前,該資料庫連線一直維持在sleep狀態!
Waiting for net, reading from net, writing to net
偶爾出現無妨
如大量出現,迅速檢查資料庫到前端的網路連線狀態和流量
案例:因外掛程式,內網資料庫大量讀取,內網使用的百兆交換迅速爆滿,導致大量連線阻塞在waiting for net,資料庫連線過多崩潰
Locked狀態
有更新操作鎖定
通常使用innodb可以很好的減少locked狀態的產生,但是切記,更新操作要正確使用索引,即便是低頻次更新操作也不能疏忽。如上影響結果集範例所示。
在myisam的時代,locked是很多高併發應用的噩夢。所以mysql官方也開始傾向於推薦innodb。
Copy to tmp table
索引及現有結構無法涵蓋查詢條件,才會建立一個臨時表來滿足查詢要求,產生巨大的恐怖的i/o壓力。
很可怕的搜尋語句會導致這樣的情況,如果是資料分析,或者半夜的週期數據清理任務,偶爾出現,可以允許。頻繁出現務必最佳化之。
Copy to tmp table通常與連表查詢有關,建議逐漸習慣不使用連表查詢。
實戰範例:
u 某社群資料庫阻塞,求救,經查,其伺服器存在多個數據庫應用和網站,其中一個不常用的小網站資料庫產生了一個恐怖的copy to tmp table操作,導致整個硬碟i/o和cpu壓力超載。Kill掉該操作一切恢復。
Sending data
Sending data並不是傳送資料,別被這個名字所欺騙,這是從物理磁盤獲取資料的程序,如果你的影響結果集較多,那麼就需要從不同的磁碟碎片去抽取資料,
偶爾出現該狀態連線無礙。
回到上面影響結果集的問題,一般而言,如果sending data連線過多,通常是某查詢的影響結果集過大,也就是查詢的索引項不夠最佳化。
如果出現大量相似的SQL語句出現在show proesslist列表中,並且都處於sending data狀態,最佳化查詢索引,記住用影響結果集的思路去思考。
Storing result to query cache
出現這種狀態,如果頻繁出現,使用set profiling分析,如果存在資源開銷在SQL整體開銷的比例過大(即便是非常小的開銷,看比例),則說明query cache碎片較多
使用flush query cache可即時清理,也可以做成定時任務
Query cache引數可適當酌情設定。
Freeing items
理論上這玩意不會出現很多。偶爾出現無礙
如果大量出現,記憶體,硬碟可能已經出現問題。比如硬碟滿或損壞。
i/o壓力過大時,也可能出現Free items執行時間較長的情況。
Sorting for …
和Sending data類似,結果集過大,排序條件沒有索引化,需要在記憶體裡排序,甚至需要建立臨時結構排序。
其他
回覆列表
排查方法 :
> mysql -uroot -p #登陸資料庫
>******** #輸入資料庫密碼
mysql> show processlist;
show processlist 命令詳解:
processlist命令的輸出結果顯示了有哪些執行緒在執行,可以幫助識別出有問題的查詢語句。
+-----+-------------+--------------------+-------+---------+-------+----------------------------------+----------
| Id | User | Host | db | Command | Time| State | Info
+-----+-------------+--------------------+-------+---------+-------+----------------------------------+----------
|207|root |192.168.0.20:51718 |mytest | Sleep | 5 | | NULL
先簡單說一下各列的含義和用途,第一列,id,不用說了吧,一個標識,你要kill一個語句的時候很有用。user列,顯示單前使用者,如果不是root,這個命令就只顯示你許可權範圍內的sql語句。host列,顯示這個語句是從哪個ip的哪個埠上發出的。呵呵,可以用來追蹤出問題語句的使用者。db列,顯示這個程序目前連線的是哪個資料庫 。command列,顯示當前連線的執行的命令,一般就是休眠(sleep),查詢(query),連線(connect)。time列,此這個狀態持續的時間,單位是秒。state列,顯示使用當前連線的sql語句的狀態,很重要的列,後續會有所有的狀態的描述,請注意,state只是語句執行中的某一個狀態,一個sql語句,已查詢為例,可能需要經過copying to tmp table,Sorting result,Sending data等狀態才可以完成,info列,顯示這個sql語句,因為長度有限,所以長的sql語句就顯示不全,但是一個判斷問題語句的重要依據。
常見問題 :
一般是睡眠連線過多,嚴重消耗mysql伺服器資源(主要是cpu, 記憶體),並可能導致mysql崩潰。
解決辦法 :
mysql的配置my.ini檔案中,有一項:
wait_timeout, 即可設定睡眠連線超時秒數,如果某個連線超時,會被mysql自然終止。
wait_timeout過大有弊端,其體現就是MySQL裡大量的SLEEP程序無法及時釋放,拖累系統性能,不過也不能把這個指設定的過小,否則你可能會遭遇到“MySQL has gone away”之類的問題,通常來說,我覺得把wait_timeout設定為10是個不錯的選擇,但某些情況下可能也會出問題,比如說有一個CRON指令碼,其中兩次SQL查詢的間隔時間大於10秒的話,那麼這個設定就有問題了(當然,這也不是不能解決的問題,你可以在程式裡時不時mysql_ping一下,以便伺服器知道你還活著,重新計算wait_timeout時間):
mysql> show global variables like "wait_timeout";
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| wait_timeout | 120 |
+----------------------------+-------+
mysql> set global wait_timeout=20;
至此,mysql佔用cpu下降了