2013-08-05 60 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在几秒钟内的变化,所以这似乎不是问题。 –