程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> Mysql鏈接池超時斷開解決方法探討

Mysql鏈接池超時斷開解決方法探討

編輯:MySQL綜合教程

Mysql鏈接池超時斷開解決方法探討


引言:昨天晚上做了個激活服務,然後測試沒問題,今天早上重新測了下,發現報異常,鏈接不上數據庫.
先說一下發生這個Exception的大致原因:
MySQL的配置中,有一個叫做“wait_timeout"的參數,這個參數大致的意思是這樣:當一個客戶端連接到MySQL數據庫後,如果客戶端不自己斷開,也不做任何操作,MySQL數據庫會將這個連接保留"wait_timeout"這麼長時間(單位是s,默認是28800s,也就是8小時),超過這個時間之後,MySQL數據庫為了節省資源,就會在數據庫端斷開這個連接;當然,在此過程中,如果客戶端在這個連接上有任意的操作,MySQL數據庫都會重新開始計算這個時間。


這麼看來,發生上面Exception的原因就是因為我的服務器和MySQL數據庫的連接超過了”wait_timeout"時間,MySQL服務器端將其斷開了,但是我的程序再次使用這個連接時沒有做任何判斷,所以就掛了。
那這個問題怎麼解決呢?
查了下網上的資料,其中詳細點的如下:


第一個問題:我們的服務器曾經在設計的過程中考慮過這個事情,所以服務器的主線程有一個定時的check機制,每隔半小時會發送一個"select 1"到數據庫來保證連接是活動的,為什麼這個check機制不起作用了呢?
第二個問題:從上面的Exception中可以得到這麼一個信息:
[java] view plaincopy
The last packet sent successfully to the server was 43200 milliseconds ago, which is longer than the server configured value of 'wait_timeout'. 這個信息說的很明白,最後一個成功發到Server的包是43200毫秒之前。但是43200毫秒才43.2秒,也就是說我們的服務器43.2秒之前才和MySQL服務器通過信,怎麼會發生超過”wait_timeout“的問題呢?而且MySQL數據庫的配置也確實是28800秒(8小時),這又是神馬情況呢?[html] view plaincopy <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.useUnicode">true</property>
<property name="hibernate.connection.characterEncoding">UTF-8</property> <property name="hibernate.show_sql">true</property>
<!-- 以下就全是mapping了,省略 --> </session-factory>
程序中更新的過程大致是這樣: [java] view plaincopy
session = org.hibernate.SessionFactory.openSession(); transaction = session.beginTransaction();
session.update(something); transaction.commit();
session.close(); 在這裡,所有關於數據庫Connection的連接和關閉都在Hibernate中,因此,不去挖掘Hibernate的源碼是不可能了。[html] view plaincopy <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.useUnicode">true</property>
<property name="hibernate.connection.characterEncoding">UTF-8</property> <property name="hibernate.show_sql">true</property>
<!-- c3p0在我們使用的Hibernate版本中自帶,不用下載,直接使用 --> <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property> <property name="hibernate.c3p0.max_statements">50</property>
<!-- 下面這句很重要,後面有解釋 --> <property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<!-- 以下就全是mapping了,省略 --> </session-factory>

 

上面配置中最重要的就是hibernate.c3p0.testConnectionOnCheckout這個屬性,它保證了我們前面說的每次取出連接時會檢查該連接是否被關閉了。不過這個屬性會對性能有一些損耗,引用我參考的博客上得話:程序能用是第一,之後才是它的性能(又不是不能容忍)。

當然,c3p0自帶類似於select 1這樣的check機制,但是就像我說的,除非你將check機制的間隔時間把握的非常好,否則,問題是沒有解決的。

好了,至此,困擾我的問題解決完了。希望上面的這些整理可以為我以後碰到類似的問題留個思路,也可以為正在被此問題困擾的人提供一絲幫助。


最後補充點東西:

1,一些c3p0的屬性方法總結:

datasource.c3p0.acquireIncrement=10當連接池中的連接用完時,C3P0一次性創建新連接的數目;

datasource.c3p0.minPoolSize=50連接池中保留的最小連接數。默認為15

datasource.c3p0.maxPoolSize=400連接池中保留的最大連接數。默認為15;

datasource.c3p0.initialPoolSize=50初始化時創建的連接數,應在minPoolSize與maxPoolSize之間取值。默認為3;

datasource.c3p0.maxIdleTime=1800最大空閒時間,超過空閒時間的連接將被丟棄。為0或負數則永不丟棄。默認為0;

datasource.c3p0.acquireRetryAttempts=100定義在從數據庫獲取新連接失敗後重復嘗試獲取的次數,默認為30;

datasource.c3p0.acquireRetryDelay=20兩次連接中間隔時間,單位毫秒,默認為1000;

datasource.c3p0.debugUnreturnedConnectionStackTraces=true

datasource.c3p0.maxStatements=0JDBC的標准參數,用以控制數據源內加載的PreparedStatement數量。但由於預緩存的Statement屬 於單個Connection而不是整個連接池。所以設置這個參數需要考慮到多方面的因素,如果maxStatements與 maxStatementsPerConnection均為0,則緩存被關閉。默認為0;

datasource.c3p0.idleConnectionTestPeriod=1800隔多少秒檢查所有連接池中的空閒連接,默認為0表示不檢查;

datasource.c3p0.breakAfterAcquireFailure=true獲取連接失敗將會引起所有等待獲取連接的線程拋出異常。但是數據源仍有效保留,並在下次調 用getConnection()的時候繼續嘗試獲取連接。如果設為true,那麼在嘗試獲取連接失敗後該數據源將申明已斷開並永久關閉。默認為 false;

datasource.c3p0.testConnectionOnCheckout=false因性能消耗大請只在需要的時候使用它。如果設為true那麼在每個connection提交的時候都 將校驗其有效性。建議使用idleConnectionTestPeriod或automaticTestTable

datasource.c3p0.autoCommitOnClose=true連接關閉時默認將所有未提交的操作回滾。默認為false;

datasource.c3p0.maxStatementsPerConnection=100連接池內單個連接所擁有的最大緩存Statement數。默認為0;

2,本問題中,再多加入<property name="hibernate.c3p0.maxIdleTime">1800</property>這一行,原因在上面屬性中有.

3,記得添加兩個jar包:我添加的版本是c3p0-0.9.2.1.jar和mchange-commons-java-0.2.3.4.jar

若後面有新的問題 隨時補充.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved