天天看點

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

mysql系統變量提供關于伺服器的一些配置和能力資訊,大部分變量可在mysqld服務程序啟動時設定,部分變量可在mysqld服務程序運作時設定。合理的系統變量設值範圍,是保障mysql穩定提供服務的重要因素。本文主要描述mysql資料庫的逾時timeout相關的一些系統變量,部分參數同程式應用中常見到的<code>communicationsexception: communications link failure</code>異常息息相關。

本文也結合資料同步的場景,對使用datax3進行mysql資料同步時遇到的幾個經典案例進行闡述,期望對遇到類似問題的同學有一定的參考作用。

mysql同逾時相關的系統變量名大都包含timeout關鍵字,使用mysql <code>show variables</code> 即可查詢目前變量值狀态,查詢sql以及結果如下:

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

下面具體介紹各個逾時系統變量的含義,内容主要翻譯和參考了mysql官方文檔。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

connect_timeout是mysql服務端程序mysqld等待連接配接建立完成的時間,機關為秒。如果超過connect_timeout時間範圍内,仍然無法完成協定握手話,mysql用戶端會收到異常,異常消息類似于: <code>lost connection to mysql server at 'xxx', system error: errno.</code> 遇到此類錯誤,一般可嘗試性增加connect_timeout時間的大小。

以plain handshake為例,在tcp三次握手建立後,進入mysql應用層協定握手階段,過程如下:

server sending initial handshake packet

client replying with handshake response packet

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

mysql服務端會有監聽線程循環接收請求,當有用戶端請求過來時,會建立線程(或者從線程池中取)來處理這個用戶端請求(一般基于網絡的應用都是這個套路,監聽線程不具體處理客戶請求)。由于mysql連接配接基于tcp協定,在mysql應用層協定建立前,需要完成tcp三次握手,在tcp三次握手成功之後,用戶端會進入阻塞,等待服務端的消息,進入應用層協定握手階段。後續服務端會建立線程(或者從線程池中取)來處理請求,這裡會進行權限相關的驗證,比如host、使用者名、密碼驗證等。host驗證即用grant指令授權使用者的時候是有指定host的(比如設定了僅允許指定ip的用戶端連接配接資料庫);使用者名密碼認證則是服務端先生成一個随機數發送給用戶端,用戶端用該随機數和密碼進行多次sha1加密後發送給服務端驗證。如果在connect_timeout時間範圍内無法完成握手,則報告建立連接配接異常。

相對于mysql資料查詢query來說,連接配接握手相對耗時較少,系統預設的10秒一般足夠了,不太會出現需要修改的場景。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

delayed_insert_timeout用于控制mysql的延遲插入(delayed inserts)逾時時間,由于在mysql 5.6.7後,延遲插入不在支援,此系統變量也不建議修改或使用。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

innodb_lock_wait_timeout指的是事務等待擷取資源等待的最長時間,超過這個時間還未配置設定到資源則會傳回應用事務失敗。參數的時間機關是秒,最小可設定為1s(一般不會設定得這麼小),最大可設定1073741824秒(34年),預設值是50秒。當鎖等待超過設定時間的時候,類似會報如下的錯誤; error 1205 (hy000): lock wait timeout exceeded; try restarting transaction。

innodb_lock_wait_timeout隻針對innodb存儲引擎下的行鎖,不影響或限制表鎖,可以通過set global 或者 set session語句在運作時修改此值。

在資料同步場景下,mysql寫出使用了批量batch送出模式,每個batch會開啟一個事務的,innodb引擎下,會受到此參數的影響。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

innodb_rollback_on_timeout隻針對innodb存儲引擎,預設為為off。on表示復原整個事務,off表示隻復原最後一條報錯的sql。如果事務因為加鎖逾時,根據innodb_rollback_on_timeout進行復原(完整事務或最後一條出錯sql),用戶端會收到報錯異常,使用者可以選擇是繼續送出,或者復原之前的操作,由使用者選擇是否進一步送出或者復原事務。

此系統變量是一個布爾狀态的參量,不是逾時時間。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

interactive_timeout表示伺服器關閉互動式連接配接前等待活動的秒數,參數預設值28800秒(8小時)。互動式用戶端(如mysql指令行)定義為在mysql_real_connect()中使用client_interactive選項的用戶端。如果某個互動式客戶連接配接在interactive_timeout秒内沒有操作動作,mysql伺服器就認為該客戶連接配接不再有保留的必要并自動關閉這個連接配接。對于非互動式的客戶連接配接,mysql伺服器将使用wait_timeout變量的值作為這種逾時等待時間。

一個互動式客戶連接配接斷開并重連的例子(mysql指令行用戶端)如下:

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

datax進行mysql資料同步時,使用的mysql驅動是mysql-connector-java 5.1.34版本,屬于非互動式用戶端。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

wait_timeout表示伺服器關閉非互動連接配接之前等待活動的秒數,參數預設值:28800秒(8小時)。線上程啟動時,根據全局wait_timeout值或全局interactive_timeout值初始化會話wait_timeout值,取決于用戶端類型(由mysql_real_connect()的連接配接選項client_interactive定義)。如果某個非互動的客戶連接配接在wait_timeout秒内沒有操作動作,mysql伺服器就将認為該客戶連接配接不再有保留的必要并自動關閉這個連接配接。對于互動式的客戶連接配接,mysql伺服器使用interactive_timeout變量的值作為這種逾時等待的秒數。這個變量僅使用于tcp/ip連接配接和unix系統上的套接字檔案連接配接。

這裡介紹和wait_timeout相關的2個場景。

假設你的資料庫是mysql,如果資料源配置不當,将可能發生經典的<b>8小時問題</b>。原因是mysql在預設情況下,如果發現一個連接配接的空閑時間超過8小時,将會在資料庫端自動關閉這個連接配接。而資料源并不知道這個連接配接已經關閉了,當它将這個無用的連接配接傳回給應用時,應用在此連接配接上執行的sql statement都會失敗。一般資料庫連接配接池(如c3p0、dbcp)都有保活機制、或者傳回連接配接前檢查連接配接的可用性。

此問題的相關異常棧一般如下所示:

<b>此系統變量對于datax資料同步有較大影響</b>。使用datax進行mysql資料同步時,datax是通過jdbc 相關接口發送資料讀取select sql語句,進而讀取mysql資料庫表資料的。如果mysql表過大、或者有不合适的資料抽取控制where條件、或者資料表缺少相關的索引機制,導緻資料讀取sql長時間不傳回,有可能到達wait_timeout時間限制值,導緻連接配接被mysql服務端關閉,資料同步任務失敗。

此時需要增大wait_timeout大小或者嘗試優化資料讀取sql(表索引、有索引列的where條件、減少不必要的函數列等)的性能。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

lock_wait_timeout是中繼資料鎖等待逾時,任意鎖中繼資料的語句都會用到這個逾時參數,預設為一年。為了保證事務可串行化,不管是myisam還是innodb引擎的表,隻要是先在一個session裡面開啟一個事務,就會擷取操作表的中繼資料鎖,這時候如果另一個session要對表的中繼資料進行修改,則會阻塞直到逾時。這個逾時會影響對表dml/ddl操作、視圖、存儲過程、存儲函數、lock tables、flush tables with read lock、handler 語句等。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

在mysql伺服器接收客戶資料的場合,如果mysql伺服器在等待了net_read_timeout秒之後仍未收到來自客戶連接配接的資料,就會産生一個讀操作逾時錯誤。這種倒計時隻适用于tcp/ip連接配接。

這裡介紹一個net_read_timeout相關的異常情景。

這裡分析判斷出現問題的原因是net_read_timeout過小導緻的,mysql服務端沒有在net_read_timeout時間範圍内讀取到用戶端mysql驅動發送過來的資料,導緻連接配接中斷。

另外,這類錯誤不一定是net_read_timeout、net_write_timeout、net_retry_count設定值不合适導緻的,也可能是網絡基礎環境、資料庫負載壓力、用戶端負載壓力等有異常情況,遇到問題時需要具體分析找到rootcase。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

在mysql伺服器往客戶發送資料的場合,如果mysql伺服器在經過了net_write_timeout秒之後仍未收到來自用戶端的響應,就将産生一個寫操作逾時錯誤。這種倒計時隻适用于tcp/ip連接配接。

這裡介紹一個net_write_timeout相關的異常情景。

一個資料同步任務,在資料讀mysql的資料過程中,出現連接配接中斷異常,問題報錯關鍵異常資訊如下:

此datax任務資料讀取sql為:select hashcode,address from geohash6_address

此datax任務已經運作一段時間,通過日志可以看到mysql讀取資料情況: total 429248 records, 371587338 bytes | speed 343.11kb/s, 329 records/s

在2016-08-23 16:22:57.904時(距離開始發起讀取sql 390秒左右)出現了communicationsexception異常,上次從服務端擷取到資料為10毫秒前,上次驅動發送資料到服務端(即服務端收到确認)396,755毫秒(396秒)前

mysql服務和逾時相關的系統變量如下圖:

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

這裡分析判斷出現問題的原因是net_write_timeout過小導緻的,mysql服務端沒有在net_write_timeout時間範圍内擷取mysql驅動的ack,連接配接中斷。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

如果mysql服務端在讀寫資料時,出現連接配接中斷,會重試net_retry_count指定的次數。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

如果從伺服器在經過slave-net-timeout秒之後仍未接收到來自主伺服器的資料,就将産生一個逾時錯誤,這種倒計時僅僅使用tcp/ip連接配接。在逾時連接配接錯誤後,從伺服器會嘗試重連,第一次嘗試重連發生在slave-net-timeout逾時觸發時,後續的重連間隔、重連次數都有相關的配置可自定義。

MySQL逾時參數以及相關資料內建、DataX資料同步案例分享一、背景二、逾時系統變量介紹三、在數加Data IDE中測試連通性

如果您在資料源測試聯通時遇到一些問題,大緻遇到的情況有:

使用者名、或密碼錯誤

由于白名單、或者mysql資料庫host通路限制,不允許連通測試機器通路您的資料庫

網絡或資料庫相關問題,沒有在指定時間内<b>3秒</b>聯通測試成功并傳回

您的資料庫連接配接格式有誤,不符合mysql jdbc url格式要求

您配置的資料庫ip、端口、有防火牆限制、是否路由可達等,此類錯誤一般異常消息大緻如下:

針對資料庫連接配接逾時相關,可能遇到的情況有:

套接字或插座(socket)是一種軟體形式的抽象,用于表達兩台機器間一個連接配接的“終端”。針對一個特定的連接配接,每台機器上都有一個“套接字”,可以想象它們之間有一條虛拟的“線纜”。java有兩個基于資料流的套接字類:serversocket,伺服器用它“偵聽”進入的連接配接;socket,用戶端用它初始一次連接配接。偵聽套接字隻能接收新的連接配接請求,不能接收實際的資料包。

以基于tcp/ip協定棧為例介紹,每一次網絡互動的sync和ack都有等待時間的上限。假如建立連接配接是設定socket逾時時間為10s,那麼當用戶端發送sync之後在10s内沒有收到服務端的ack資訊就會逾時。通常java會抛sockettimeoutexception。socket通信失效後下面除login timeout的其他逾時機制均會失效。

socket逾時時間可以在連接配接的url中指定。對于mysql,可以在jdbc url中指定socket逾時時間,如将設定socket逾時為10s:

login timeout是jdbc嘗試連接配接database最長等待時間。在jdbc和database握手過程中每個階段都會檢查是否逾時,如果逾時會抛socketexception異常,登出連接配接。可以通過drivermanager.setlogintimeout(10)設定。

用戶端和伺服器建立的應用層連接配接,與伺服器端無互動狀态的連接配接,直到被伺服器端強制關閉而等待的時間,此參數隻對基于tcp/ip或基于socket通信協定建立的連接配接才有效,機關為秒。連接配接的建立涉及到資源的配置設定,如連接配接池資源。可以通過連接配接串設定。如:

用戶端發送一個sql等待伺服器傳回最大等待時間,用戶端在發送sql之前會設定一個timer,如果在指定等待時間内還未收到伺服器的執行結果,則會向伺服器發出取消sql執行指令。并抛出sqlexception。設定方法:statement.setquerytimeout(100);注意:如果socket通信阻塞,這個異常是抛不出來的,方法調用會阻塞在向伺服器發送取消指令。