1. 程式人生 > >資料庫連結斷開 Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

資料庫連結斷開 Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

報錯資訊如下:

Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 97,130 milliseconds ago. The last packet sent successfully to the server was 24 milliseconds ago.
; SQL []; Communications link failure
....
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

產生問題的直接原因:

  1. 資料庫重啟
  2. 資料庫空閒連線超過設定的最大timemout時間

導致資料庫會強行斷開已有的連結,就會報這個異常。

產生問題的根本原因:

以mysql5版本為例,其自身連線的等待時間(wait_timeout)預設為8小時,如果在wait_timeout秒期間內,資料庫連線(java.sql.Connection)一直處於等待狀態,mysql5就將該連線關閉。這時,你的Java應用的連線池仍然合法地持有該連線的引用。當用該連線來進行資料庫操作時,就會產生上述錯誤。

問題解決:

一、馬上止損的方法:

重啟伺服器。(重啟伺服器,資料庫連線池就會重新初始化, 重新獲取和資料庫的有效連線)

二、避免產生上述問題的方法:【你需要自己按自己採用的連線池,型別去搜索相應的配置,不同連線池可能不同】

  1. 資料庫連線池增加探活配置。(在連線池配置檔案中增加下面的關鍵屬性) (推薦這種方式)

    為了解決這個異常,我們在配置資料庫連線池的時候需要做一些檢查連線有效性的配置,這裡以Druid為例,相關配置如下(更多配置):這裡還有一個(dbcp的配置

    欄位名 預設值 說明
    validationQuery   用來檢測連線是否有效的sql,要求是一個查詢語句,常用select 'x'。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會起作用。
    validationQueryTimeout   單位:秒,檢測連線是否有效的超時時間。底層呼叫jdbc Statement物件的void setQueryTimeout(int seconds)方法
    testOnBorrow true 申請連線時執行validationQuery檢測連線是否有效,做了這個配置會降低效能。
    testOnReturn false 歸還連線時執行validationQuery檢測連線是否有效,做了這個配置會降低效能。
    testWhileIdle false 建議配置為true,不影響效能,並且保證安全性。申請連線的時候檢測,如果空閒時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連線是否有效。
    timeBetweenEvictionRunsMillis 1分鐘(1.0.14) 有兩個含義:1) Destroy執行緒會檢測連線的間隔時間,如果連線空閒時間大於等於minEvictableIdleTimeMillis則關閉物理連線。2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明

    為了避免空閒時間過長超過最大空閒時間而被斷開,我們設定三個配置:

    validationQuery: SELECT 1
    testWhileIdle: true
    timeBetweenEvictionRunsMillis: 28000

    其中timeBetweenEvictionRunsMillis需要小於mysql的wait_timeout

     

  2. 增大資料庫預設的超時等待時間(wait_timeout) 【如果太大,可能導致連線數較多,引起效能下降】

    修改MySQL的引數,wait_timeout最大為31536000即1年,在my.cnf中加入:
    [mysqld]
    wait_timeout=31536000
    interactive_timeout=31536000
    重啟生效,需要同時修改這兩個引數。

     

  3. JDBC配置Mysql連線URL重連機制

    jdbc:mysql://localhost:3306/test?user=root&password=&autoReconnect=true

     

  4. JDBC減少連線池內連線生存週期:使之小於所設定的wait_timeout 的值

    <property name="maxIdleTime" value="1800" />