前言: 本文是對Muhammad Irfan的這篇博客MySQL "Got an Error Reading Communication Packet" Errors的翻譯,如有翻譯不對或不好的地方,敬請指出,大家一起學習進步。尊重原創和翻譯勞動成果,轉載時請註明出處。謝謝! 英文原文地址:http... ...
前言: 本文是對Muhammad Irfan的這篇博客MySQL "Got an Error Reading Communication Packet" Errors的翻譯,如有翻譯不對或不好的地方,敬請指出,大家一起學習進步。尊重原創和翻譯勞動成果,轉載時請註明出處。謝謝!
英文原文地址:https://www.percona.com/blog/2016/05/16/mysql-got-an-error-reading-communication-packet-errors/
翻譯原文地址:http://www.cnblogs.com/kerrycode/p/9075214.html
在這篇博客中,我們來討論一下引起MySQL出現”Got an error reading communication packet”錯誤的可能原因,以及如何解決這個錯誤。
在Percona的托管服務中,我們經常收到客戶關於通信故障錯誤的問題—客戶面臨間歇性的”Got an error reading communication packet”錯誤,我認為這個話題值得寫一篇博客,所以我們在這裡討論這個錯誤出現的可能原因,以及如何解決這個問題。我希望這些能夠幫助讀者如何調查和解決這個問題。
首先,當通信故障錯誤出現時,MySQL的狀態變數Aborted_clients和Aborted_connects的計數會增加。這兩個狀態變數描述了由於客戶端沒有正確關閉連接而導致中斷的連接數以及那些嘗試登錄MySQL失敗的連接數量(分別)。兩個錯誤出現的可能原因很多(請參考官方文檔關於Aborted_clients increments or Aborted_connects increments 章節)。
在系統變數log_warnings > 1的情況下,MySQL會將這些信息寫入錯誤日誌(如下所示):
[Warning] Aborted connection 305628 to db: 'db' user: 'dbuser' host: 'hostname' (Got an error reading communication packets)
[Warning] Aborted connection 305627 to db: 'db' user: 'dbuser' host: 'hostname' (Got an error reading communication packets)
在下麵這些情況下, MySQL會增加Aborted_clients狀態變數的計數,這可能意味著:
o 客戶端已經成功連接,但是異常終止了(可能與未正確關閉連接有關係)
o 客戶端休眠時間超過了系統變數wait_timeout或interactive_timeout的定義值(最終導致連接休眠的時間超過系統變數wait_timeout的值,然後被MySQL強行關閉)
o 客戶端異常中斷或查詢超出了max_allowed_packet值。
上面不是一個包括了全部可能原因的列表,現在,我們來聊聊如何識別導致這個問題的原因以及如何解決這個。
我們如何識別導致此問題的原因,以及如何解決、修複這個問題呢?
老實來說,連接中斷錯誤不容易診斷,但根據我的經驗,大部分時候它跟網路/防火牆問題有關,我們通常在Percona Toolkit腳本的幫助下來調查這些問題。例如pt-summary / pt-mysql-summary / pt-stalk 這些腳本的輸出信息非常有幫助。
其中的一些可能原因:
在MySQL內部,大量的MySQL連接處於休眠狀態並休眠了數百秒是應用程式在完成工作後沒有關閉連接的癥狀之一,它們依靠wait_tiemout系統變數來關閉連接。 我強烈建議修改應用程式邏輯,在操作結束後正確關閉連接。
檢查並確保max_allowed_packet的值足夠大,並且客戶端沒有收到“packet Too large”這種消息,這種情況會導致連接中斷而無法正常關閉連接。
另外一種可能性是TIME_WAIT, 我註意到了許多來自netstat的TIME_WAIT通知,所以我建議在應用程式端管理好連接並關閉連接。
確保事務正確的提交(begin 和 commit),以便一旦應用程式完成後,它保持乾凈狀態。
你應該確保客戶端應用程式不會終止連接。 例如,如果PHP將選項max_execution_time設置成5秒,則增加connection_timeout將無濟於事, 因為PHP將終止該腳本。其它編程語言和環境可能有類似的安全選項。
引起連接延遲的另外一個原因是DNS問題,檢查是否啟用了跳過名稱解析,以及主機是否針對其IP地址而不是其主鍵名進行身份驗證。
找出應用程式錯誤行為的一種方法在代碼中增加一些日誌記錄,以便將應用程式的操作與MySQL連接標識信息一起保存。這樣你可以將它與錯誤行中的連接號關聯起來。啟用PerConna審計日誌插件(Audit log plugin),記錄連接和查詢活動,併在你遇到連接中斷時檢查Percona Audit Log Plugin的日誌,以確定哪個查詢是罪魁禍首。如果你由於某種原因不能使用Audit插件,你可以考慮使用MySQL的查詢日誌,儘管在負荷較高的伺服器可能有風險, 你也應該啟用查詢日誌至少幾分鐘。雖然它給伺服器帶來了沉重的負擔,由於錯誤往往會經常發生,所以你應該能夠在日誌變得過大前收集到所需的數據,我建議使用啟用查詢日誌並使用tail -f來查看查詢日誌,當你在查詢日誌中看到下一個告警出現時,就禁用查詢日誌。
一旦你從中斷的連接中找到一些查詢語句後,在應用程式中找到使用這些查詢的相關應用程式部分。
嘗試增加MySQL的系統變數net_read_timeout 和 net_write_timeout 的值,看看是否會減少錯誤的數量,net_read_timeout是很少出現的異常,除非你的網路環境實在是太糟糕了,嘗試調整這些值,因為在大多數情況下,會生成一個查詢並將其作為單個數據包發送到伺服器,並且應用程式無法切換到執行其他操作,而將伺服器保留作為部分接收的查詢。我們的首席執行官Peter Zaitsev關於這個話題有一篇非常詳細的博客文章。
中斷連接的出現是因為連接未正確關閉。除非伺服器和客戶端直接存在網路問題(例如,伺服器是半雙工,客戶端是全雙工),否則伺服器不會導致連接中斷,所以引起問題的是網路,而不是伺服器,在任何情況下,這些問題應該顯示為網路介面上的錯誤,為了更加確定,請在MySQL伺服器上使用ifconfig -a命令輸出相關信息。以檢查是否有錯誤。
解決這個問題的另外一個方法是通過tcpdump工具,你可以參考這篇博客,瞭解如何追蹤連接中斷的來源,查找潛在的網路問題、超時和與 MySQL 相關的資源問題。
我發現這篇博客對解釋如何在繁忙的主機上使用tcpdump非常有用,它為跟蹤導致中止連接的TCP交換序列提供了幫助,這可以幫助您找出連接斷開的原因。
對於網路問題,使用ping命令計算mysqld所在的伺服器與應用程式發出請求的機器之間的往返時間(RTT),從客戶端向伺服器發送大文件(1GB或更大),使用tcpdump觀察進程,然後檢查傳輸過程中是否發生錯誤。重覆這個測試。我也從我的同事Marco Tusa那裡找到了這個有用的方法: 檢查網路連接的有效方法。
對於網路問題,使用ping來計算mysqld所在的機器與應用程式發出請求的機器之間的往返時間(RTT)。向客戶機和伺服器機器發送大文件(1GB或更多),使用tcpdump觀察進程,然後檢查傳輸過程中是否發生錯誤。重覆這個測試幾次。我也從我的同事Marco Tusa那裡找到了這個有用的方法:檢查網路連接的有效方法。
我能想到的另一個想法是在每N秒後捕獲一次netstat -s輸出和一個時間戳(例如,10秒鐘,這樣您就可以將BEFORE和AFTER中斷連接錯誤的netstat -s輸出與MySQL錯誤日誌相關聯) 。通過中斷連接錯誤的時間戳,您可以將它與根據netstat時間戳記捕獲的netstat示例進行共同關聯,並觀察在netstat -s的TcpExt部分下增加了哪些錯誤計數器。
除此之外,還應該檢查位於客戶端和伺服器之間的網路基礎架構,從代理(proxies),負載平衡器和防火牆那些可能導致問題的方面入手。
結論:
我試圖涵蓋通信失敗錯誤(communication failure errors),以及如何識別和修複可能的連接中斷問題。考慮到乙太網,集線器,交換機,電纜等故障也會導致此問題。您必須更換硬體才能正確診斷這些問題。