背景
生產環境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
反思:
上面貼出來的排查方向,是主要正確方向,也有很多錯誤方向和無關重要的方向就沒有貼出來了,排查過程異常緊張和曲折,希望下次遇到類似的問題能迎刃而解了。