2013-08-05 61 views
0

我體驗了一種使用hibernate的奇怪行爲。 我有一個使用hibernate和spring的java web應用程序,使用MySQL數據庫。Hibernate池似乎釋放連接

症狀: 通過期運用檢查我的SQL連接的會話:

show processlist; 

我可以看到我的數據源配置定義的連接的數量,但是當時間的推移他們的ID是變化的,讓我相信連接正在關閉,然後重新連接。 即使沒有流量時也會發生此行爲。
我希望彙集的連接將他們的ID保留在數據庫上。

配置:

<bean id="DataSource" 
    class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="${url}" /> 
    <property name="username" value="${username}" /> 
    <property name="password" value="${password}" /> 
    <property name="maxWait" value="10" /> 
    <property name="maxIdle" value="5" /> 
    <property name="maxActive" value="0" /> 
    <property name="validationQuery" value="SELECT 1"/> 
    <property name="testOnBorrow" value="true" /> 
    <property name="testOnReturn" value="true"/> 
    <property name="testWhileIdle" value="true"/> 
    <property name="timeBetweenEvictionRunsMillis" value="10000"/> 
    <property name="minEvictableIdleTimeMillis" value="60000"/>  
</bean> 
<bean id="SessionFactory" 
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="DataSource"></property> 
    <property name="mappingResources"> 
     <list> 
      <value> 
       data/entities/entity.hbm.xml 
      </value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect"> 
       org.hibernate.dialect.MySQLDialect 
      </prop> 
     </props> 
    </property> 
</bean> 

<bean id="entityDaoImpl" class="data.dao.EntityDaoImpl"> 
    <property name="sessionFactory" ref="SessionFactory" /> 
</bean> 

<bean id="SessionFactory2" 
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="DataSource"></property> 
    <property name="mappingResources"> 
     <list> 
      <value> 
       data/entities/entity2.hbm.xml 
      </value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect"> 
       org.hibernate.dialect.MySQLDialect 
      </prop> 
     </props> 
    </property> 
</bean> 

<bean id="entity2DaoImpl" class="data.dao.Entity2DaoImpl"> 
    <property name="sessionFactory" ref="SessionFactory2" /> 
</bean> 

我的猜測是,它可以連接到一個事實,即2個不同的會話工廠都使用相同的數據源,但我相信我錯過了一些更深入的瞭解(或者是權不知道爲什麼,或者完全錯誤)

我將補充說我使用spring 2.5和運行在tomcat 6上的Hibernate 3.1.1。 我注意到許多地方人們不鼓勵使用hibernateTemplate,但代碼使用它。

編輯:

我打開了審計,試圖弄清楚哪些連接正在做的和我專注於一個我看到的是由自我封閉:

130806 10:58:43  13 Connect  [email protected] on database 
130806 10:58:43  13 Query  SET NAMES hebrew 
130806 10:58:43  13 Query  SET character_set_results = NULL 
130806 10:58:43  13 Query  SHOW VARIABLES 
130806 10:58:43  13 Query  SHOW COLLATION 
130806 10:58:43  13 Query  SET autocommit=1 
130806 10:58:43  13 Query  SET sql_mode='STRICT_TRANS_TABLES' 
130806 10:58:43  13 Query  SELECT 1 
130806 10:58:43  13 Query  SET autocommit=1 
130806 10:58:54  13 Query  SET autocommit=1 
130806 10:58:54  13 Query  SELECT 1 
130806 10:58:54  13 Query  SET autocommit=1 
130806 10:59:25  13 Query  SET autocommit=1 
130806 10:59:25  13 Query  SELECT 1 
130806 10:59:25  13 Query  SET autocommit=1 
130806 11:00:27  13 Quit 

至於我的理解表明,自從他獲得Quit命令後,問題不在數據庫方面。 所以我再次懷疑在我的數據源配置中是否存在一些keepAlive配置?

感謝

回答

0

我找到了這種行爲的原因。 根是參數minEvictableIdleTimeMillis。

該參數文檔說:

的最小時間量的對象可能在池閒置之前,它是用於eligable由空閒對象逐出器(如果有的話)驅逐。

在我的情況下,這意味着60秒後,如果閒置連接可能會被驅逐。

參數timeBetweenEvictionRunsMillis文件說:

的毫秒數空閒對象逐出器線程的運行之間睡覺。如果不是肯定的,則不會運行閒置的對象清除線程。

在我的情況下,驅逐檢查每10秒發生一次。 另一參數在我的配置缺少的是numTestsPerEvictionRun記載:

空閒對象逐出器線程(如果有的話)的每個運行期間檢查對象的數量。

在我的情況下,3個連接(默認)檢查驅逐。

因此總共每10秒(除了第一分鐘的應用程序被加載)我的10個連接中的3個將被驅逐。即使它們在閒置時使用validationQuery進行測試(testWhileIdle爲true)。

我認爲validationQuery查詢檢查將重置空閒時間計數(因爲通過連接發送查詢)。 但我錯了。

因此,最終解決方案是將minEvictableIdleTimeMillis設置爲600000而不是60000,導致我的空閒連接停留時間更長。

1

的MySQL殺死wait_timeout後的空閒連接。您的連接池檢測到它們已經死亡並重新連接它們。

一切都很好...

+0

所以它不會影響我的應用程序? 是wait_timeout是mysql的配置嗎? 是否有一個數據源有多個會話工廠的問題? –

+0

這是MySQL的正常行爲。是的,'my.cnf'中設置了'wait_timeout'。 –

+0

我檢查my.cnf,看到我使用wait_timeout的默認值。這是28800秒,並且我看到了ID在幾秒鐘內的變化,所以這似乎不是問題。 –