之前遇到開發詢問“mysql server has gone away”的問題,想當然的就認為是由於太長時間沒有操作,導致超過MySQL服務端上的wait_timeout的設置,最終連接被MySQL服務端回收了。
最近一次突然自己同事寫的腳本在運行過程中被中斷了,查看報錯信息依然是“mysql server has gone away”,同事的腳本在多個MySQL實例上根據時間范圍取值,雖然執行時間長了點,但是絕對不會有超過wati_timeout的空閒等待時間,於是去學習了一下到底有哪幾種情況會出現這個報錯。
就是最常見的,一個鏈接超過wait_timeout的設置時間沒有做任何事情,被MySQL服務端關閉鏈接並回收資源。
針對這種情況要不調大wait_timeout或者不斷的向MySQL服務端發送心跳信號,保持鏈接。
你的鏈接被kill掉了,有可能是DBA人工操作,也可能是各種自動化系統操作,可以通過監控status中com_kill狀態值來判斷剛才是否發生了kill操作。
MySQL的客戶端如果默認配置中有mysql_opt_read_timeout或者mysql_opt_write_timeout參數,並且操作時間超過了其中一個參數的設置,客戶端自身會關閉鏈接。所以需要了解自己使用的mysql客戶端。
還有一種可能是發送的請求或者返回的結果集太大了,超過MySQL的max_allowed_packet_size的設置,導致發生這種報錯。多說一句,這個參數需要客戶端和服務端同時配置並保持一致才會生效。
最常見的Linux上的mysql客戶端可以使用如下命令查看:
mysql allowedpacket
我們可以看到我們服務器上默認的設置為16M。
這種比較罕見的情況是MySQL服務端的DNS反解失敗導致,理論上我們可以配置–skip-networking參數來規避這種問題。(但是官方文檔居然說即使配置了也可能出現這種報錯,T_T)
還有就是如果程序使用了多進程,而所有進程都嘗試使用同一個鏈接和MySQL服務端建立鏈接的時候就會出現gone away的報錯了。(初步懷疑,這也就是我同事遇到的問題了。)
最後這種比較弱,但是真實發生過,那就是mysql實例宕機了。實例都沒有了,自然什麼都沒有了。當然這種情況判斷起來比較方便,一般都會有mysql的存活監控。但是要小心一種情況,就是實例crash後迅速recover,如果監控程序的間隔大於recover的時間,那麼就很難發現了。建議使用如下方法復查一下,另外針對uptime最好做為狀態的一個必要監控點。
show global status Variable_name Value Uptime