在C API中調用mysql_options()來設置mysql_init() 所建立的鏈接對象的屬性,使用這三個選項能夠設置鏈接超時和讀寫超時,單位都是秒。讀寫超時達到後C API的查詢發送和結果獲取函數會返回超時錯誤。mysql
MYSQL_OPT_CONNECT_TIMEOUTsql
MYSQL_OPT_READ_TIMEOUT數據庫
MYSQL_OPT_WRITE_TIMEOUT服務器
也能夠使用配置文件來設置鏈接超時和交互超時:網絡
connect-timeout=secondssocket
interactive-timeout=seconds函數
當客戶端API在向mysql server發起鏈接connect-timeout秒後沒有收到mysql server的相應那麼認爲鏈接失敗。post
interactive-timeout是用於這個客戶端鏈接的交互超時。交互超時用於在交互界面程序(好比mysql這個鏈接客戶端程序)中設置server的會話超時時間,來賦值給wait_timeout會話變量,它一般比較大,由於使用這個交互界面的一般是人類在手動操做,而不是程序執行和發送指令。mysql server默認使用會話變量@@wait_timeout 做爲會話的超時,除非在mysql_real_connect中使用CLIENT_INTERACTIVE標誌來標識這個鏈接是用於交互操做,此時若是客戶端有interactive-timeout就使用它來做爲本會話的會話超時,不然使用服務器端的interactive-timeout做爲會話超時設置給wait_timeout。spa
從下圖中能夠看出,服務器端關於超時的變量有不少,這裏去掉了咱們的TDSQL特有的非標準的MySQL/MariaDB的幾個超時值。其中的connect_timeout, net_read_timeout, net_write_timeout,slave_net_timeout, interactive_timeout和wait_timeout與網絡IO有關。線程
其中,connect_timeout 被用於在用戶登陸期間,也就是創建數據庫鏈接期間,做爲mysql server端的網絡讀寫超時。這與文檔上面的說法並不相同,可是代碼中確實是這樣子的。
net_read_timeout 和net_write_timeout是數據庫會話建立好以後mysql server端使用的讀寫超時。若是讀取或者寫入操做在等待了達到超時後服務器認爲客戶端鏈接斷開,執行錯誤處理。
而slave_net_timeout是slave的io線程使用客戶端C API鏈接master時候,調用mysql_options()來設置MYSQL_OPT_CONNECT_TIMEOUT,MYSQL_OPT_READ_TIMEOUT,MYSQL_OPT_WRITE_TIMEOUT這三個超時選項使用的值。IO線程鏈接master使用的都是標準的客戶端C API代碼和通訊協議。
最後,wait_timeout是mysqld server的默認的會話超時,若是一個數據庫鏈接(會話)在這麼長時間以後沒有任何讀寫動做,那麼這個鏈接被關閉。interactive_timeout是默認的交互式鏈接的會話超時,會設置給wait_timeout,若是客戶端有自定義的值,那麼那個值會被優先使用來設置給wait_timeout。
全部這些超時能夠分爲鏈接超時,讀寫超時和會話超時三類,下面就講一下這些超時機制是如何實現的。
在Linux的connect(), recv, send, read(), write()等系統調用中,並不能夠簡單地阻塞等待一段指定時間後再返回錯誤,而是要麼把文件句柄設置爲非阻塞的(使用fcntl()和O_NONBLOCK標誌,或者對於recv/send()能夠每次調用使用MSG_DONTWAIT)而且馬上返回,要麼一直阻塞等待。因此,要實現超時仍是要一點小技巧的。另外,MySQL中網絡IO的代碼不管是客戶端C API的網絡IO功能仍是服務器內部使用的網絡通訊功能,都是同一份代碼實現,所以下文不須要區分客戶端和服務器端。
相關函數:vio_socket_connect(),vio_io_wait()
首先,若是有鏈接超時時間的話,就設置socket fd爲非阻塞的,而後調用標準的socket函數connect()來發起鏈接,這個函數會當即返回-1而且設置errno爲 EINPROGRESS或者EALREADY。而後,調用vio_io_wait()來使用poll()來阻塞等待這個鏈接能夠寫入,使用鏈接超時值做爲poll()的超時參數。這樣,在等待超時後就認爲鏈接失敗,不然鏈接就成功了。這裏並無使用網絡協議本身的鏈接超時,由於那樣的話沒法在不影響其餘進程的狀況下隨時靈活更改這個超時時間。
相關函數:vio_read(), vio_write(), vio_socket_io_wait()
首先,調用標準的recv()/send()系統調用來讀取或者寫入,若是有讀寫超時時間的話,就使用MSG_DONTWAIT做爲最後一個flags參數,這樣若是沒有數據能夠讀取或者沒法寫入(好比網絡擁塞)這個函數會馬上返回SOCKET_EAGAIN 或者SOCKET_EWOULDBLOCK,因而,調用vio_socket_io_wait()來阻塞等待這個socket fd能夠讀或者寫,這個函數主要是調用了poll(),而且用讀寫超時值做爲poll()的等待超時時間。
這裏的會話(Session)其實就是數據庫鏈接,在mysql內部對應於THD類。會話超時是Mysql server端纔有的機制,在客戶端沒有。實現方法是:Mysql server內部線程按期檢查全部THD會話對象的狀態,將會話超時的THD對象銷燬。