当达到 max_size 时,c3p0 不释放连接
c3p0 not releasing connection when max_size reached
我试图用一种方法对数据库执行 10 次获取。
我正在使用 Hibernate 3.5.x 和 Spring 3.2.13 以及 c3p0 0.9.5.
我的 hibernate.cfg.xml 包含以下内容:
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="hibernate.c3p0.min_size">10</property>
<property name="hibernate.c3p0.timeout">600</property>
通过 c3p0 的调试,一切正常:
[managed: 10, unused: 0, excluded: 0]
[managed: 10, unused: 1, excluded: 0]
[managed: 10, unused: 2, excluded: 0]
[managed: 10, unused: 3, excluded: 0]
[managed: 10, unused: 4, excluded: 0]
[managed: 10, unused: 5, excluded: 0]
[managed: 10, unused: 6, excluded: 0]
[managed: 10, unused: 7, excluded: 0]
[managed: 10, unused: 8, excluded: 0]
[managed: 10, unused: 9, excluded: 0]
这一切发生得非常快(不到 0.5 秒)
但是,如果我添加一个额外的 get,即 11,那么我会得到以下结果:
[managed: 10, unused: 0, excluded: 0] repeatedly
直到连接超时才会改变。
我正在使用 Springs 事务管理器,如下所示:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
并使用以下基本上调用 findOne()
public abstract class AbstractDAO<T extends Serializable> {
private Class< T > clazz;
@Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void setClazz(final Class<T> clazzToSet) {
clazz = clazzToSet;
}
@Transactional
public T findOne(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
...
}
请告诉我还有哪些其他信息可能有助于诊断。
我哪里做错了?
您正在泄漏连接。
您未能关闭() 您的连接。 (请在组织的 finally 块中稳健地关闭()它们,以便保证对 close() 的调用——即不能被 finally 中的先前异常跳过——或者如果 Java 7+ 使用 try-with-resources.
注意:在 Hibernate 中,您必须确保关闭连接的是 Session。
所以看起来你不能在同一个线程中使用超过 hibernate.c3p0.max_size 的连接,即如果 hibernate.c3p0.max_size 设置为 10,那么你不能在同一个线程中使用 11 个连接.我猜 c3p0 只有在线程完成后才会释放连接。
我对此进行测试的方法是让 10 次进入方法,然后休眠 15 秒。我执行了该方法两次,第一个方法 运行 使用了 10 个连接。 15 秒后,该方法完成,第二次执行 运行 成功用完另外 10 个连接,然后在 15 秒后释放。
我想我能理解为什么会这样。我想我将不得不 refactor/redesign 我对连接的使用...
更新:
我发现这个 hibernate.connection.release_mode 属性 我设置为 after_statement。这似乎在执行后释放了连接。有关详细信息,请参阅 here
我试图用一种方法对数据库执行 10 次获取。 我正在使用 Hibernate 3.5.x 和 Spring 3.2.13 以及 c3p0 0.9.5.
我的 hibernate.cfg.xml 包含以下内容:
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="hibernate.c3p0.min_size">10</property>
<property name="hibernate.c3p0.timeout">600</property>
通过 c3p0 的调试,一切正常:
[managed: 10, unused: 0, excluded: 0]
[managed: 10, unused: 1, excluded: 0]
[managed: 10, unused: 2, excluded: 0]
[managed: 10, unused: 3, excluded: 0]
[managed: 10, unused: 4, excluded: 0]
[managed: 10, unused: 5, excluded: 0]
[managed: 10, unused: 6, excluded: 0]
[managed: 10, unused: 7, excluded: 0]
[managed: 10, unused: 8, excluded: 0]
[managed: 10, unused: 9, excluded: 0]
这一切发生得非常快(不到 0.5 秒)
但是,如果我添加一个额外的 get,即 11,那么我会得到以下结果:
[managed: 10, unused: 0, excluded: 0] repeatedly
直到连接超时才会改变。
我正在使用 Springs 事务管理器,如下所示:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
并使用以下基本上调用 findOne()
public abstract class AbstractDAO<T extends Serializable> {
private Class< T > clazz;
@Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void setClazz(final Class<T> clazzToSet) {
clazz = clazzToSet;
}
@Transactional
public T findOne(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
...
}
请告诉我还有哪些其他信息可能有助于诊断。
我哪里做错了?
您正在泄漏连接。
您未能关闭() 您的连接。 (请在组织的 finally 块中稳健地关闭()它们,以便保证对 close() 的调用——即不能被 finally 中的先前异常跳过——或者如果 Java 7+ 使用 try-with-resources.
注意:在 Hibernate 中,您必须确保关闭连接的是 Session。
所以看起来你不能在同一个线程中使用超过 hibernate.c3p0.max_size 的连接,即如果 hibernate.c3p0.max_size 设置为 10,那么你不能在同一个线程中使用 11 个连接.我猜 c3p0 只有在线程完成后才会释放连接。
我对此进行测试的方法是让 10 次进入方法,然后休眠 15 秒。我执行了该方法两次,第一个方法 运行 使用了 10 个连接。 15 秒后,该方法完成,第二次执行 运行 成功用完另外 10 个连接,然后在 15 秒后释放。
我想我能理解为什么会这样。我想我将不得不 refactor/redesign 我对连接的使用...
更新: 我发现这个 hibernate.connection.release_mode 属性 我设置为 after_statement。这似乎在执行后释放了连接。有关详细信息,请参阅 here