NO IMAGE

之前在使用SSH開發專案的時候遇到了一個很奇怪的問題,部署到伺服器上,執行一段時間後系統就崩潰了。

出現錯誤:org.hibernate.exception.JDBCConnectionException: could not execute query
 

在後在百度上查了下資料發現了問題所在,原來這個是傳說中的8小時問題— —。

一、什麼是8小時問題?

Mysql伺服器預設的“wait_timeout”是8小時,也就是說一個connection空閒超過8個小時,Mysql將自動斷開該
connection。這就是問題的所在,在Hibernate預設連線池中的connections如果空閒超過8小時,Mysql將其斷開,而Hibernate預設連線池並不知道該connection已經失效,如果這時有 Client請求connection,Hibernate預設連線池將該失效的Connection提供給Client,將會造成上面的異常。 

二、解決的方法

1. 增加 MySQL 的
wait_timeout 屬性的值。

修改 /etc/mysql/my.cnf 檔案,在 [mysqld] 節中設定:

# Set a connection to wait 8 hours in
idle status.
wait_timeout = 86400
或者在MySQL中使用SQL語句:
set global interactive_timeout=
86400;
set global wait_timeout=
86400;

相關網路資料:
mysql> show variables like ‘%timeout%’;
————————– ——-
| Variable_name            | Value |
————————– ——-
| connect_timeout           | 5     |
| delayed_insert_timeout   | 300   |
| innodb_lock_wait_timeout  | 50    |
| interactive_timeout       | 28800 |
| net_read_timeout          | 30    |
| net_write_timeout         | 60    |
| slave_net_timeout         | 3600 |
| wait_timeout              | 28800 |
————————– ——-          
同一時間,這兩個引數只有一個起作用。到底是哪個引數起作用,和使用者連線時指定的連線引數相關,預設情況下是使用wait_timeout。我建議是將這兩個引數都修改,以免引起不必要的麻煩。

這兩個引數的預設值是8小時(60*60*8=28800)。

測試將這兩個引數改為0,結果出人意料,系統自動將這個值設定為28800 。

換句話說,不能將該值設定為永久。
將這2個引數設定為1年(60*60*24*365=31536000)

總不至於一年都不用這個連結吧?
set interactive_timeout=31536000;
set wait_timeout=31536000;

結果:

wait_timeout 的設定出現警告,再看看設定後的結果

也就是說wait_timeout的最大值只允許2147483 (24天左右)

2. 減少連線池內連線的生存週期,使之小於上一項中所設定的 wait_timeout 的值。

修改 c3p0 的配置檔案,設定:

# How long to keep unused connections around(in seconds)
# Note: MySQL times out idle connections after 8 hours(28,800 seconds)
# so ensure this value is below MySQL idle timeout
cpool.maxIdleTime=25200

在 Spring 的配置檔案中:

  1. <bean id=”dataSource”  
  2.      class=”com.mchange.v2.c3p0.ComboPooledDataSource”>  
  3.     <property name=”maxIdleTime” value=”${cpool.maxIdleTime}” />  
  4.     <!– other properties –>  
  5. </bean>  

3. 定期使用連線池內的連線,使得它們不會因為閒置超時而被 MySQL 斷開。

c3p0連線池的配置方法:

修改 c3p0 的配置檔案,設定:

# Prevent MySQL raise exception after a long idle time
cpool.preferredTestQuery='SELECT 1'
cpool.idleConnectionTestPeriod=18000
cpool.testConnectionOnCheckout=true

修改 Spring 的配置檔案:

  1. <bean id=”dataSource”  
  2.        class=”com.mchange.v2.c3p0.ComboPooledDataSource”>  
  3.     <property name=”preferredTestQuery”  
  4.            value=”${cpool.preferredTestQuery}” />  
  5.     <property name=”idleConnectionTestPeriod”  
  6.            value=”${cpool.idleConnectionTestPeriod}” />  
  7.     <property name=”testConnectionOnCheckout”  
  8.            value=”${cpool.testConnectionOnCheckout}” />  
  9.     <!– other properties –>  
  10. </bean> 

c3p0連線池的配置方法:

proxool連線池的配置方法:

http://blog.csdn.net/risingsun001/article/details/12197715

注:網上所說的 設定 "autoReconnect=true" 的方法,測試無效,