【问题标题】:c3p0 connection is overduec3p0 连接过期
【发布时间】:2015-02-03 15:10:02
【问题描述】:

我正在使用 c3p0 0.9.2.1、GWT 2.6.0、SQLServer 2012。

我从 c3p0 收到间歇性 stackTrace

[2015-Feb-03 16:30:12] - [INFO ] - A checked-out resource is overdue, and will be destroyed: com.mchange.v2.c3p0.impl.NewPooledConnection@14bc0e
[2015-Feb-03 16:30:12] - [INFO ] - Logging the stack trace by which the overdue resource was checked-out.
java.lang.Exception: DEBUG STACK TRACE: Overdue resource check-out stack trace.
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:555)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutAndMarkConnectionInUse(C3P0PooledConnectionPool.java:755)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:682)
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:140)
    at org.hibernate.c3p0.internal.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:89)
    at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:380)
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228)
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:171)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.connection(StatementPreparerImpl.java:63)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:162)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:186)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:160)
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1884)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1861)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1838)
    at org.hibernate.loader.Loader.doQuery(Loader.java:909)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
    at org.hibernate.loader.Loader.doList(Loader.java:2551)
    at org.hibernate.loader.Loader.doList(Loader.java:2537)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2367)
    at org.hibernate.loader.Loader.list(Loader.java:2362)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:126)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1678)
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:380)
    at net.impro.portal.server.model.dao.CommsQueueDaoImpl.getOldestRecords(CommsQueueDaoImpl.java:54)
    at net.impro.portal.server.engine.uploader.AbstractBiometricUploader.getOldestRecords(AbstractBiometricUploader.java:217)
    at net.impro.portal.server.engine.uploader.UploaderMorpho$$EnhancerByGuice$$9212bdc2.getOldestRecords(<generated>)
    at net.impro.portal.server.engine.uploader.AbstractUploader.getSomeQueueData(AbstractUploader.java:222)
    at net.impro.portal.server.engine.uploader.UploaderMorpho$$EnhancerByGuice$$9212bdc2.getSomeQueueData(<generated>)
    at net.impro.portal.server.engine.uploader.AbstractBiometricUploader.processLoop(AbstractBiometricUploader.java:92)
    at net.impro.portal.server.engine.uploader.AbstractUploader.run(AbstractUploader.java:172)
    at java.lang.Thread.run(Unknown Source)

所以,它告诉我我在指定的超时时间内没有完成连接

<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces" value="true" />
<property name="hibernate.c3p0.unreturnedConnectionTimeout" value="10" />

我不明白这怎么可能。我的代码很简单……

@Transactional
 protected void getSomeQueueData() {
   logger.error("+Entered Thread " + Thread.currentThread());
   //A little clumsy here but I dont see anything wrong
   final CommsQueueDao commsQueueDao = InjectHelp.requestNewInstance(CommsQueueDao.class);
   List<CommsQueue> qData = getOldestRecords(commsQueueDao, MAX_LOCAL_QUEUE_SIZE);
   Iterator<CommsQueue> iterator = qData.iterator();
   //Iterate the result, pack it into a local queue
   //...         
   logger.error("-Exit Thread " + Thread.currentThread() + " " + stuffToSend.size());
 }

@Transactional
  protected List<CommsQueue> getOldestRecords(CommsQueueDao qDao, int fetchSize) {
  return qDao.getOldestRecords(getBioAddress(), fetchSize);
}


//FROM MY DAO CLASS
public List<CommsQueue> getOldestRecords(BioAddress bioAddress, int maxRecords) {
  Criteria cr = getSession().createCriteria(CommsQueue.class);
  cr.add(Restrictions.eq("bioAddress", bioAddress));
  cr.addOrder(Order.asc("id"));
  cr.setMaxResults(maxRecords);
  return cr.list();
}

启动时,25 个线程启动,每个线程调用 getSomeQueueData()。大约 1/10 次失败。我检查调试输出,发现每个线程都按预期在几秒钟内成功进入和退出该方法,那么为什么 c3p0 告诉我连接仍在使用中?澄清一下,@Transactional 是 guice,而不是 spring。

---编辑--- 我已经花了很多时间调查这个问题,它只会变得更加令人费解......

我也将 c3p0 更新到了 0.9.5

由于某种原因,@Transactional 似乎不稳定。偶尔它不会被调用。我检查通过我的 DAO 的每个方法的堆栈跟踪,并且每隔一段时间,它表明拦截器处理已被跳过??。

在我的 DAO 中,我有一个 getSession() 方法,当我添加任意 sleep 100ms 时,几乎每个 stackTrace 都表明注释已被跳过。

此外,这些设置几乎每次都会出现问题

<property name="hibernate.c3p0.maxPoolSize" value="20" />
<property name="hibernate.c3p0.minPoolSize" value="1" />
<property name="hibernate.c3p0.numHelperThreads" value="1" />

...这些设置使问题很少发生

<property name="hibernate.c3p0.maxPoolSize" value="20" />
<property name="hibernate.c3p0.minPoolSize" value="20" />
<property name="hibernate.c3p0.numHelperThreads" value="20" />

据我的测试显示,完全删除 c3p0 似乎可以完全解决问题。

我已经读过,对于 guice 使用反射的情况,使用 finally 是需要提防的,我一直小心避免这种情况。这些症状太奇怪了,我无法缩小范围。有时 guice 似乎没有正确绑定我的类,有时似乎是 c3p0 错误。

哦,我检查过我使用的是 com.google.inject.persist.Transactional。

【问题讨论】:

  • 您是否在某个时间点在您的会话中致电close()?
  • 这是一个 Java 问题,与 GWT 没有任何关系。更新您的标签以增加获得答案的机会。
  • 我不调用 close() 因为 Transactional 应该负责会话管理。我认为如果 Transactional 的行为不符合我的预期,它可能与 GWT 有关。我将添加一个 java 标签。谢谢。
  • 您的导入中 Transactional 注释的包是什么?
  • 我没有代码,但我认为它是 com.google.inject.persist。我想我真的应该说 Transactional 与 google guice 而不是 gwt 有关。

标签: java c3p0 guice-persist


【解决方案1】:

在没有解决问题的情况下尝试了替代池库后,我将注意力转向依赖注入。我认为问题与 guice 托管类的 constructor 中存在的代码有关。如果该代码的效果有可能调用标记为@Transactional 的方法,则在“跳过”事务注释的情况下可能会出现此问题。

这对我来说似乎很有意义,所以我已将其从构造函数中移出。在我确信这是解决方案之前,我会继续监视它一段时间。

【讨论】:

    猜你喜欢
    • 2014-12-23
    • 2011-01-07
    • 2011-07-19
    • 2013-08-20
    • 2016-07-08
    • 2012-04-22
    • 1970-01-01
    • 2011-02-18
    • 2015-11-20
    相关资源
    最近更新 更多