【問題現象】
開發同事反饋有應用在21:00-22:00之間出現大量超時報錯。
【問題分析】
1、 從DB服務器慢查詢指標來看,18:00后有大量的慢查詢,累計產生了約9000條慢查詢
2、 測試直接執行慢查詢SQL語句,並沒有發現性能問題
3、當時DBA同事在排障現場看到了線程執行時等待Writing to net。
之前我們碰到過大量Writing to net等待的情況,通常是DB服務器網卡流量打滿導致。但這次從DB服務器網卡流量上看,並沒有打滿,而且比較平穩。
從QPS和threads_running指標來看,並發不是很高,相對平穩。
4、 Writing to net狀態究竟代表了什么
Writing to net
The server is writing a packet to the network.
這里先簡單描述下SQL語句查詢的流程:
<1>掃描一行,寫到net_buffer,這里net buffer 是按照net_buffer_length 初始化, 但可以動態增長到max_allowed_packet配置值
<2>繼續獲取滿足條件的行,直到寫滿net_buffer,然后調用網絡接口發送出去
<3>客戶端接收網絡包完成,清空net_buffer
<4>重復上面1到3的步驟
<5>如果發送未完成,表示socket send buffer寫滿,這時會進入等待狀態,顯示Writing to net,直到socket send buffer重新可寫,再繼續發送
下面是MySQL5.6.21的代碼片段:
static const char *thread_state_info(THD *tmp)
{
#ifndef EMBEDDED_LIBRARY
if (tmp->net.reading_or_writing)
{
if (tmp->net.reading_or_writing == 2)
return "Writing to net";
else if (tmp->get_command() == COM_SLEEP)
return "";
else
return "Reading from net";
}
else
#endif
{
if (tmp->proc_info)
return tmp->proc_info;
else if (tmp->mysys_var && tmp->mysys_var->current_cond)
return "Waiting on cond";
else
return NULL;
}
}
由於MySQL是邊掃描邊發送數據的,當客戶端接收慢時,就會阻塞整個查詢進程,導致執行變慢。
注意MySQL5.7.8以后,狀態發生了變化
Sending to client
The server is writing a packet to the client. This state is called Writing to net
prior to MySQL 5.7.8.
5、 在網絡通信的鏈路上,DB端網絡沒有問題,需要繼續排查網絡通信緩存區瓶頸,以及客戶端的網絡或處理。
當時排障時,DBA嘗試調整放大了max_allowed_packet參數,但是效果不明顯。
從應用服務器的網絡指標,可以看出從中午12:35-00:00間,有大量套接字處於連接狀態establish。與DB端的慢查詢趨勢基本一致。
6、到這里基本可以定位問題是由於WEB客戶端接收處理DB端發送的網絡包比較慢,導致了SQL語句處於Writing to net狀態,執行很慢。
這里可能是WEB應用服務器異常,或WEB客戶端或宿主機的網絡問題。
7、后面聯系了相關同事,排查到這台WEB服務器對應的宿主機相關的交換機在這段時間有性能問題。
數據庫運維經驗分享&MySQL源碼學習漫漫路