mysqli::real_connect(): (08004/1040): Too many connections,MySql操作緩慢:copying to tmp table

背景

生產環境MySQL數據庫突然打開了很多鏈接Too many connections,導致整個網站癱瘓了2個小時,網站無法訪問,重啓數據庫重啓服務器都無濟於事,由於我們項目相對來說比較龐大,經過無數人的打磨,所以給排查帶來了一定的困難,於是得空總結了下這兩個小時的漫長的時間的排查解決思路和方法。

MySQL error log

頭次遇到這樣的問題,難免感覺束手無策,大致有如下排查方向:

看線上進程,看運行SQL,看運行最久的,看SQL狀態。

問題排查

方向1:有人建議:max_connections  這個值可以先改大一點臨時解決一下問題先  。其實這裏是嚴重的bug,估計改大也沒多大意義,主要還是要找到問題的進程SQL。

方向2:執行 show processlist命令

註解:show processlist 是顯示用戶正在運行的線程,需要注意的是,除了 root 用戶能看到所有正在運行的線程外,其他用戶都只能看到自己正在運行的線程,看不到其它用戶正在運行的線程。除非單獨個這個用戶賦予了PROCESS 權限。

方向3:執行show variables like ‘%timeout%’命令

查看超時,或鎖死情況。得出結論:使用數很大,但是沒有鎖 。

方向4:執行show engine innodb status命令

那show engine innodb status 展示了多少信息,這些信息對系統的狀態,如果不知道怎麼看看看 這篇博文

發現有個sql 一直在 copy tmp table,connect數一直在增,buffer緩衝池已經佔用完了。

再次執行 show processlist 查看當前的SQL進程,專門認真分析了下

最後發現真正的罪魁禍首,這條SQL一直在執行,並copying to tmp table 複製到臨時表中,找到這條SQL也就知道是什麼業務了,原來是 "異常通知的服務" 定時任務,後面臨時停了這個業務,網站得以恢復訪問,接着專門對該業務做緊急優化。

 

最後總結

是由於前一天上線版本中,有人給表加字段加索引導致的,第一天由於是晚上系統空閒期,沒有發現該問題,第二天工作人員用該系統就一直打不開了。 

關鍵步驟:
主要執行 show processlist,看到所有操作表的線程 
發現 state狀態爲copy to tmp table,這是因爲臨時結果集大於tmp_table_size,正在將臨時表從內存存儲轉爲磁盤存儲以此節省內存

解決方案:

暫時停掉該SQL的業務,緊急優化sql。更多MySQL優化方法請看這篇博文:https://blog.csdn.net/u012104435/article/details/50915604

反思:

上面貼出來的排查方向,是主要正確方向,也有很多錯誤方向和無關重要的方向就沒有貼出來了,排查過程異常緊張和曲折,希望下次遇到類似的問題能迎刃而解了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章