閱讀1012 返回首頁    go 阿裏雲 go 技術社區[雲棲]


MySQL · 答疑解惑 · MySQL 的那些網絡超時錯誤

前言

我們在使用/運維 MySQL 過程中,經常會遇到一些網絡相關的錯誤,比如:

Aborted connection 134328328 to db: 'test' user: 'root' host: '127.0.0.1' (Got timeout reading communication packets)

MySQL 的網絡超時相關參數有好幾個,這個超時到底是對應哪個參數呢?

在之前的月報中,我們介紹過 MySQL 的 網絡通信模塊 ,包括各模塊間的關係,數據網絡包是如何發送接受的,以及結果集的數據格式,大家可以先回顧下。

這裏我們對 mysqld 處理網絡包時,遇到的超時異常情況進行分析,希望大家在遇到網絡相關的報錯時,能更好理解和排查問題。

問題分析

MySQL 是平等網絡協議,就是說 client 和 server 之間的網絡交互是一來一回的,client 發送完請求後,必須等待 server 響應包回來,才能發下一個請求。
對 mysqld 來說,就是接收網絡請求,然後內部處理,將結果集返回給客戶端,然後等待下一個請求:

先看下 mysqld server 和網絡超時相關的參數有哪些:

  • interactive_timeout
  • wait_timeout
  • net_read_timeout
  • net_write_timeout
  • connect_timeout

在底層實現上,不管是讀還是寫操作,超時都是通過 poll(&pfd, 1, timeout) 做的,參數之間的區別是針對連接的不同狀態。

讀超時

wait_timeout 是給讀請求用的,在 do_command 開始就做設置:

my_net_set_read_timeout(net, thd->variables.net_wait_timeout);

這個時候,連接是空閑的,等待用戶的請求。

等讀完用戶的請求包後,連接就變成 active 的,在調用 dispatch_command 執行 SQL 前,通過

my_net_set_read_timeout(net, thd->variables.net_read_timeout);

把超時設置回 net_read_timeout,之後在執行 SQL 請求過程中,server 和 client 基本不會有網絡交互,所以這個超時基本用不上。

有一個特殊的情況是 LOAD DATA LOCAL FILE 命令,server 在執行過程中,需要和 client 再做網絡交互。

interactive_timeout 是給交互模式的客戶端使用的,比如我們常用的 mysql client 工具,這個是在認證過程中設置的,邏輯如下:

static void
server_mpvio_update_thd(THD *thd, MPVIO_EXT *mpvio)
{
  thd->client_capabilities= mpvio->client_capabilities;
  thd->max_client_packet_length= mpvio->max_client_packet_length;
  if (mpvio->client_capabilities & CLIENT_INTERACTIVE)
    thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
  thd->security_ctx->user= mpvio->auth_info.user_name;
  if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
    thd->variables.sql_mode|= MODE_IGNORE_SPACE;
}

如果客戶端的能力位上設置了 CLIENT_INTERACTIVE,會用 interactive_timeout 的值覆蓋 wait_timeout 的值。
而一般情況下,我們應用在建立連接時,是不會設置這個能力位的。

寫超時
net_write_timeout 對應寫超時,在連接認證完成後,server 和 client 交互過程中寫超時一真是不變的。

認證超時

connect_timeout 是給連接認證過程用的,讀和寫都用這個值,認證完成後,讀和寫分別設置為 net_read_timeoutnet_write_timeout

總結

可以看到和讀相關的超時參數是最多的,也比較容易搞混亂。

  1. 如果是認證過程中超時,不管是讀還是,都是 connect_timeout;
  2. 對於讀網絡超時,一般是 wait_timeout/interactive_timeout,基本不會是 net_read_timeout(特例是業務用到 LOAD DATA LOCAL FILE);
  3. 對於寫網絡超時,都是 net_write_timeout。

在遇到超時情況下,可以根據這些原則判斷對那個參數做調整。

比如下麵這種情況:

2017-05-15 19:32:41 47930 [Warning] Aborted connection 6 to db: 'unconnected' user: 'root' host: 'localhost' (Got timeout reading communication packets)

很可能需要調整的 wait_timeout/interactive_timeout。

2017-05-15 20:06:27 5063 [Warning] Aborted connection 12 to db: 'test' user: 'root' host: 'localhost' (Got timeout writing communication packets)

需要調整 net_write_timeout

需要注意的是,MySQL 的關於網絡的錯誤,除了超時以外都認為是 error,沒有做進一步的細分,比如可能會看到下麵這種日誌,有可能是客戶端異常退出了,也有可能是網絡鏈路異常。

2017-05-15 19:34:57 47930 [Warning] Aborted connection 8 to db: 'unconnected' user: 'root' host: 'localhost' (Got an error reading communication packets)

2017-05-15 20:07:39 5063 [Warning] Aborted connection 13 to db: 'test' user: 'root' host: 'localhost' (Got an error writing communication packets)

最後更新:2017-05-21 09:01:44

  上一篇:go  HybridDB · 最佳實踐 · HybridDB 數據合並的方法與原理
  下一篇:go  PgSQL · 特性分析 · 數據庫崩潰恢複(上)