【问题标题】:Hibernate pool seems to release connections休眠池似乎释放连接
【发布时间】:2013-08-05 20:31:22
【问题描述】:

我在使用休眠时遇到了一种奇怪的行为。 我有一个使用 hibernate 和 spring 的 java web 应用程序,使用 MySQL 数据库。

症状: 使用以下命令检查我的 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 个不同的会话工厂使用相同的数据源这一事实有关,但我相信我错过了一些更深入的理解(或者是对的,但不知道为什么,或者完全错了)

我还要补充一点,我使用在 tomcat 6 上运行的 spring 2.5 和 Hibernate 3.1.1。 我注意到在很多地方人们不鼓励使用 hibernateTemplate 但代码正在使用它。

编辑:

我打开了审计,试图弄清楚连接在做什么,我专注于我看到的一个自己关闭的:

130806 10:58:43      13 Connect     user@localhost 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 配置?

谢谢

【问题讨论】:

    标签: java mysql spring hibernate pool


    【解决方案1】:

    MySQL 在wait_timeout 之后终止空闲连接。您的连接池检测到它们已死并重新连接它们。

    一切都好...

    【讨论】:

    • 所以它不会影响我的申请? wait_timeout是mysql配置吗?一个数据源有多个会话工厂有问题吗?
    • 这是 MySQL 的正常行为。是的,wait_timeout 设置在 my.cnf 中。
    • 我检查了 my.cnf 并看到我正在使用 wait_timeout 的默认值。这是 28800 秒,我可以在几秒钟内看到 id 的变化,所以这似乎不是问题。
    【解决方案2】:

    我已经找到了这种行为的原因。 根是参数minEvictableIdleTimeMillis。

    这个参数文档说:

    一个对象在被空闲对象驱逐者(如果有的话)驱逐之前可以在池中闲置的最短时间。

    就我而言,这意味着如果空闲 60 秒后连接可能会被驱逐。

    参数 timeBetweenEvictionRunsMillis 文档说:

    空闲对象驱逐线程运行之间休眠的毫秒数。当为非肯定时,不会运行空闲的对象驱逐线程。

    在我的例子中,驱逐检查每 10 秒发生一次。 我的配置中缺少的另一个参数是 numTestsPerEvictionRun 记录:

    在每次运行空闲对象驱逐线程(如果有)期间要检查的对象数。

    在我的情况下,检查 3 个连接(默认)是否被驱逐。

    所以总而言之,每 10 秒(加载第一分钟应用程序除外)我的 10 个连接中的 3 个将被驱逐。即使他们在空闲时使用 validationQuery 进行了测试(testWhileIdle 为真)。

    我认为 validationQuery 查询检查将重置空闲时间计数(因为正在通过连接发送查询)。 但我错了。

    所以最后的解决方案是将 minEvictableIdleTimeMillis 设置为 600000 而不是 60000,从而导致我的空闲连接停留更长时间。

    【讨论】:

      猜你喜欢
      • 2016-07-15
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-27
      • 1970-01-01
      • 2013-12-29
      相关资源
      最近更新 更多