1. 程式人生 > >關於MySQL資料庫連線超時問題的分析與解決

關於MySQL資料庫連線超時問題的分析與解決

作業系統 Windows 10 Enterprise,資料庫 MySQL-5.5.16,c3p0-0.9.5.2

關於針對資料庫的連線,之前沒有特別注意過,直到遇到如下問題:

Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 54,812,410 milliseconds ago. The last packet sent successfully to the server was 54,812,411 milliseconds ago. is longer than the server configured value of ‘wait_timeout’. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property ‘autoReconnect=true’ to avoid this problem

從上面的資訊得知,應用程式與資料庫伺服器的連線中斷了,那麼為什麼會出現上面的問題呢?不是有連線池嗎?裡面不是儲存有大量的連線嗎?比如使用c3p0資料來源配置如下:

ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setInitialPoolSize(5);
dataSource.setMaxPoolSize(20);
dataSource.setAcquireIncrement(1);

錯誤資訊中已經說得很明白了,上一次客戶端和服務的通訊已經是54812411ms前了,但是MySQL預設配置的wait_timeout

屬性確是28800s,也就是8小時,該引數的意義是MySQL在沒有進行通訊的連線上等待的最長時間直到伺服器關閉該連線,上文資訊中指出不通訊的間隔已經有54812.411s了,所以客戶端與資料庫伺服器的連線已經被伺服器強制關閉了,所以才會出現如上的錯誤。

但是資訊中也給出了可以解決的辦法,如下:

  • 使連線過期
  • 對連線的有效性進行測試
  • 增加資料庫伺服器的超時時間
  • 使用autoReconnect屬性避免
  • 通過捕捉異常來重試建立連線

上述幾種方法可以從範圍上分成資料庫層次、應用層次。

一、資料庫層次上解決

1.1 通過增大wait_timeout的值

使用這種方式是最直接、最暴力的,通過增加該屬性的值可以增大MySQL伺服器在不活躍的連線上等待的時間,但是這種方式影響的範圍很大,因為資料庫的使用面向的應用肯定不止一個,所以如果不在萬不得已的情況之下,不要使用這種方式。

1.2 配置autoReconnect屬性

表明資料庫驅動是否會重新建立不活躍的連線,預設情況下是false。一般是在JDBC的連線URL中使用。如果設定為true,對於在不活躍的連線上進行的查詢會丟擲異常,這些查詢屬於當前的事務,事務中進行下一次查詢時,驅動將會重新建立連線。這個屬性不推薦使用,因為它對於會話狀態和資料一致性會造成影響,尤其是當應用不能正確的處理SQLExceptions時。在考慮強一致性的時候,尤其要避免使用該屬性。

二、應用層次上解決

2.1 使連線過期

此處使用的是c3p0資料來源,在該資料來源下配置連線的過期時間是通過maxIdleTime屬性實現的,該屬性的意義是:一個不使用的連線在資料庫連線池中存在的最長時間,直到它被連線池拋棄。單位是秒,預設值是0,表示連線池中的連線永遠不會過期。

ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setMaxIdleTime(1800);

配置的屬性值要大於wait_timeout的值,以免在MySQL伺服器強制斷開連線之後,連線還沒有過期。

2.2 對連線有效性進行測試

對與資料庫伺服器的連線進行有效性的測試是一個可行的方式,可以隨時確定資料庫伺服器是否可用,而不僅僅是連線是否可用。這裡使用c3p0資料來源作為示例進行,其他的資料來源,比如DBCPdruid其中也有相對應的方式完成這種操作。

c3p0提供了很多的方式來對連線池中的連線進行測試,通過這種測試來避免在應用程式的層次上看到上文中提到的錯誤。通過以下幾個屬性來完成這種測試:

下面三個屬性是控制什麼時候進行測試連線。

  • idleConnectionTestPeriod:如果該屬性的值大於0,每隔固定的時間段,c3p0會測試所有閒置、保持在連線池中的連線。預設情況下是不進行測試的;
  • testConnectionOnCheckout:是否在取連線進行測試;
  • testConnectionOnCheckin:是否在放入連線時進行測試;

下面三個屬性是決定如何進行測試連線。

  • automaticTestTablec3p0會自動建立一個空表以備查詢進行連線測試;
  • connectionTesterClassNameConnectionTester介面的全限定名實現, 預設值是com.mchange.v2.c3p0.impl.DefaultConnectionTester,用來定義c3p0資料來源如何測試連線,過於靈活,避免過度使用;
  • preferredTestQuery:定義的被用來執行連線測試的查詢;

2.2.1 進行測試的時候要考慮的問題

在進行連線測試的時候,需要考慮很多其他的問題。然後根據這些需要考慮的額外的問題來確定最佳的測試方法。

2.2.1.1 效能問題

效能問題是一個非常重要的話題,尤其是在大型的複雜應用中,在測試有效性時,也不要給連線帶來過大的負擔。

首先要考慮連線測試的時機

  • 從連線池中取出連線時:這種測試是最簡單,也是最可靠的,但是會給客戶端的效能帶來極大的影響,可以通過配置屬性testConnectionOnCheckout=true來開啟在此時進行測試;
  • 連線放入連線池時:此時進行測試時,需要同時結合idleConnectionTestPeriod,可以滿足較高的可靠性,可以通過設定testConnectionOnCheckin=true,在這種情況下,在閒時和放入連線時進行非同步測試,效能依然不會下降;

其次要考慮測試的語句

  • 如果使用的資料庫驅動支援JDBC4,並且使用的c3p0是0.9.5或以上。可以直接呼叫JDBC的API來處理,其中有一個isValid()方法可以用來實現作為快速且可靠的連線測試。預設情況下,c3p0使用這個方法進行測試。如果想要設定一個超時時間,可以通過繼承IsValidOnlyConnectionTester來實現,如下:

    public class Tester extends IsValidOnlyConnectionTester{
      protected int getIsValidTimeout() { return 30; }
    }
  • 如果驅動不支援最新的API,預設情況下c3p0通過在連線上呼叫DatabaseMetaDatagetTables()方法。這樣可以與任何型別的資料庫有效相容,但是由於返回很大的資料量會對資料庫連線池的效能造成顯著影響;在JDBC3驅動以下(或者0.9.5版本之前)可以配置preferredTestQuery加速測試,但它優先於資料來源進行載入,此時如果資料庫中沒有對應的表,則會造成錯誤,如下:

    這裡寫圖片描述

    對於這種情況,則可以通過設定automaticTestTable屬性來代替,c3p0會自動的建立一個空表來作為測試查詢的物件;

2.2.1.2 相容性問題

另外一個要考慮的是資料庫相容問題,比如需要相容多種資料庫時,比如同時要測試的資料庫有MySQLSQL ServerOracle,則需要考慮測試語句的通用性。在這種情況下可以通過可以設定與資料庫和表無關的語句,比如select 1來測試這個連線。但是針對不同資料庫型別,支援的這種輕量級的測試語句並不相同,如下對不同的常見的資料庫的支援:

語句 資料庫型別
select 1 H2、MySQL、SQL Server、PostgreSQL、SQLite
select 1 from DUAL Oracle

以上的資訊來自於這篇文章

2.2.1.3 靈活性的問題

如果對於資料來源提供的測試方法或者需要自定義一些行為時,靈活性的問題就很重要了。

c3p0也提供了這樣的支援,通過配置connectionTesterClassName屬性,提供給實現類的完全限定名即可。這種情況不需要preferredTestQuery或者automaticTestTable,預設情況下該屬性的值是com.mchange.v2.c3p0.impl.DefaultConnectionTester。可以通過繼承DefaultConnectionTester的父類AbstractConnectionTester實現。簡單實現如下:

public class MyConnectionTester extends AbstractConnectionTester {

    public int activeCheckConnection(Connection c, String preferredTestQuery, Throwable[] rootCauseOutParamHolder) {
        try {
            ResultSet resultset = c.createStatement().executeQuery("SELECT 1");
            while(resultset.next()){
                int result = resultset.getInt(1);
                if(result == 1){
                    System.out.println("test successfully");
                } else{
                    System.out.println("test failed");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return 0;
    }

    public int statusOnException(Connection c, Throwable t, String preferredTestQuery, Throwable[] rootCauseOutParamHolder) {
        return 0;
    }
}

配置如下:

ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setIdleConnectionTestPeriod(3);
dataSource.setConnectionTesterClassName("com.lmy86263.MyConnectionTester");

2.3 針對連線斷開進行重試

由於目前所有的應用都是直接使用資料來源來管理與資料庫的連線,而在程式內部只是提供一些必須的配置項,所以如果要重試則需要通過程式設計手段來完成,如下在建立資料來源的時候如果連線失敗則會重試指定次數:

ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser("root");
dataSource.setPassword("abc");

int retry = 3;
while(retry > 0){
    try {
        dataSource.getConnection();
        break;
    } catch (SQLException e) {
        retry--;
    }
}

如果對JDBC的超時的詳細機制比較感興趣可以參考最後一篇文章。

相關文章:

相關推薦

關於MySQL資料庫連線超時問題的分析解決

作業系統 Windows 10 Enterprise,資料庫 MySQL-5.5.16,c3p0-0.9.5.2 關於針對資料庫的連線,之前沒有特別注意過,直到遇到如下問題: Could not open JDBC Connection for

mysql報錯 DuplicateKeyException分析解決

在做資料庫同步的時候,發現一個錯誤,mysql報錯如下: org.springframework.dao.DuplicateKeyException: ### Error updating database. Cause: com.mysql.jdbc.exce

NUMA導致的MySQL伺服器SWAP問題分析解決方案

【SWAP產生原理】 先從swap產生的原理來分析,由於linux記憶體管理比較複雜,下面以問答的方式列了一些重要的點,方便大家理解:  1、swap是如何產生的 swap指的是一個交換分割槽或檔案,主要是在記憶體使用存在壓力時,觸發記憶體回收,這時可能會將部分記憶體的資料交換到swap空間。  2、

node.js伺服器mysql資料庫連線超時的問題(Error: connect ETIMEDOUT)

node.js伺服器mysql資料庫連線超時的問題 在node伺服器連線資料庫的時候有時候會連線超時,也就是這個錯誤Error: connect ETIMEDOUT.在程式碼的錯誤位置是mysql的connection.js檔案的421到433行程式碼:

mysql慢查詢原因分析解決(三)——索引及查詢優化

索引的型別 Ø 普通索引:這是最基本的索引型別,沒唯一性之類的限制。 Ø 唯一性索引:和普通索引基本相同,但所有的索引列值保持唯一性。 Ø 主鍵:主鍵是一種唯一索引,但必須指定為”PRIMARY KEY”。 Ø 全文索引:MYSQL從3.23.23開始支援全

MySql資料庫連線超時處理

博主在做web開發時遇到MySql資料庫連線超時的問題。 控制檯報錯如下: Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransact

連線MySQL資料庫時常見故障問題的分析解決

===================================================================================錯誤資訊 :ERROR 2003 (HY000): Can't connect to MySQL server on 'hostxxxxx' (

java連線MySQL資料庫時常見故障問題的分析解決

初學的mysql經常會碰到mysql無法連線的錯誤。收集的這樣問題的現象和原因。   歸納如下: 0.更改mysql root賬號密碼 mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpas

docker中的mysql資料庫連線不上解決辦法

1.在docker內部連線不上mysql資料庫 即在本地模式下不能連線 這時候應該是docker容器重啟過,mysql資料庫沒有啟動的原因,可以使用 service mysql restart 來啟動mysql資料庫 2.在宿主機上不能遠端連線到docker容器中的mysql資料

Mysql學習總結(63)——Mysql資料庫架構方案選擇分析

一、資料庫架構原則 高可用 高效能 一致性 擴充套件性 二、常見的架構方案 方案一:主備架構,只有主庫提供讀寫服務,備庫冗餘作故障轉移用 jdbc:mysql://vip:3306/xxdb 高可用分析:高可用,主庫掛了,keepalive(只是一種工具)會

MySql資料庫連線查詢自關聯(七)

先看個問題 問:查詢每個學生每個科目的分數 分析:學生姓名來源於students表,科目名稱來源於subjects,分數來源於scores表,怎麼將3個表放到一起查詢,並將結果顯示在同一個結果集中呢

Navicat連線阿里雲(centos7.3)的MySQL資料庫遇到的問題及解決方法

注:本文涉及到的解決方案都是我遇到的問題的對應解決方案,不一定適用於每一個人,如果問題仍然存在,請繼續百度查詢其他解決方法 1.  首先是登入阿里雲MySQL的一些必要資訊(登入其他雲主機的mysql同理): 使用ssh的方式連線到linux,具體連線引數的填寫見下圖 注意:網上很多教程寫的連線方式中“主機名

高併發場景下的快取+資料庫雙寫不一致問題分析解決方案

1、最初級的快取不一致問題以及解決方案問題:先修改資料庫,再刪除快取,如果刪除快取失敗了,那麼會導致資料庫中是新資料,快取中是舊資料,資料出現不一致。解決思路:先刪除快取,再修改資料庫,如果刪除快取成功了,如果修改資料庫失敗了,那麼資料庫中是舊資料,快取中是空的,那麼資料不會

高併發場景下的快取 資料庫雙寫不一致問題分析解決方案設計

馬上開始去開發業務系統 從哪一步開始做,從比較簡單的那一塊開始做,實時性要求比較高的那塊資料的快取去做 實時性比較高的資料快取,選擇的就是庫存的服務 庫存可能會修改,每次修改都要去更新這個快取資料; 每次庫存的資料,在快取中一旦過期,或者是被清理掉了,前端的ngin

解決資料庫連線超時的問題

檢視資料庫的連線超時時間show global variables like 'wait_timeout'; 2.在擁有許可權的情況下直接使用sql語句進行設定set global wait_timeout=90;3.在許可權不足的情況下可以通過修改spring-co

25-02、高併發場景下的快取+資料庫雙寫不一致問題分析解決方案設計

馬上開始去開發業務系統, 從哪一步開始做,從比較簡單的那一塊開始做,實時性要求比較高的那塊資料的快取去做, 實時性比較高的資料快取,選擇的就是庫存的服務, 庫存可能會修改,每次修改都要去更新這個快取資料; 每次庫存的資料,在快取中一旦過期,或者是被清理掉了,前端的nginx服務都會發送請

重新學習Mysql資料庫5:根據MySQL索引原理進行分析優化

本文出自我的公眾號:程式設計師江湖。 滿滿乾貨,關注就送。 一:Mysql原理與慢查詢 MySQL憑藉著出色的效能、低廉的成本、豐富的資源,已經成為絕大多數網際網路公司的首選關係型資料庫。雖然效能出色,但所謂“好馬配好鞍”,如何能夠更好的使用它,已經成為開發工程

遠端連線伺服器上的MySQL資料庫出現1130錯誤的解決辦法

問題背景: win2003servers系統,mysql5.0資料庫, MySQL-Front連線工具(以下簡稱MF) 問題:通過MF連線資料庫,出現ERROR 1130 (HY000): Host ‘xxx.xxx.xxx.xxx’ i

資料庫鎖表的分析解決(三)

ORACLE裡幾種鎖模式 遇到一個多事務併發的問題 mysql資料庫鎖 推薦圈子: Pipboy 更多相關推薦 對鎖機制的研究要具備兩個條件: 1.資料量大 2.多個使用者同時併發 如果缺少這兩個條件,資料庫不容易產生死鎖問題。研究起來可能會事倍功半。如果這兩個條件都有,但

dbcp資料庫連線超時解決方案

1.  問題 Could not open Hibernate Session for transaction; JDBC begin failed 2.  解決方案 MySQL 的預設設定下,當一個連線的空閒時間超過8小時後,MySQL 就會斷開該連線,而 c3p0 連線