c3p0 挂在 awaitAvailable 与休眠

Posted

技术标签:

【中文标题】c3p0 挂在 awaitAvailable 与休眠【英文标题】:c3p0 hangs in awaitAvailable with hibernate 【发布时间】:2012-12-15 20:51:01 【问题描述】:

我的控制台应用程序在执行期间挂起。这是我的配置:

    cfg.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
    cfg.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/db?user=db&password=db");
    cfg.setProperty("hibernate.connection.username", "db");
    cfg.setProperty("hibernate.connection.password", "db");
    cfg.setProperty("hibernate.connection.pool_size", "5");
    cfg.setProperty("hibernate.connection.autocommit", "false");
    cfg.setProperty("hibernate.c3p0.min_size", "5");
    cfg.setProperty("hibernate.c3p0.max_size", "20");
    cfg.setProperty("hibernate.c3p0.timeout", "300");
    cfg.setProperty("hibernate.c3p0.max_statements", "50");
    cfg.setProperty("hibernate.c3p0.idle_test_period", "3000");

这是我的堆栈跟踪:

"main" prio=10 tid=0x000000000168f800 nid=0x1c37 in Object.wait() [0x00007fa60d0ad000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007400f4c68> (a com.mchange.v2.resourcepool.BasicResourcePool)
        at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1315)
        at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557)
        - locked <0x00000007400f4c68> (a com.mchange.v2.resourcepool.BasicResourcePool)
        at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477)
        at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525)
        at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
        at org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:84)
        at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:281)
        at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:297)
        at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:169)
        at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67)
        at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160)
        at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1392)
        at org.kriyak.parser.IndexArchiveRapid.indexFile(IndexArchiveRapid.java:70)
        at org.kriyak.parser.IndexArchiveRapid.main(IndexArchiveRapid.java:53)

我只打开了一个连接,似乎没有泄漏它们。而且我也使用一个线程。除了内存使用,我没有调整任何 mysql 设置。 Mysql 在控制台上工作正常。为什么会发生这种情况?这是 c3p0 错误吗?

【问题讨论】:

这是您应用程序中唯一的线程吗? 是的,它是唯一的线程 【参考方案1】:

这会立即发生,还是在一段时间后发生?也就是说,结帐最初是否成功,但随后就这样挂起?如果是这样,它看起来像一个连接泄漏。请尝试设置 c3p0 参数 unreturnedConnectionTimeout 和 debugUnreturnedConnectionStackTraces 以查看是否存在泄漏。看 http://www.mchange.com/projects/c3p0/#configuring_to_debug_and_workaround_broken_clients,http://www.mchange.com/projects/c3p0/#unreturnedConnectionTimeout,http://www.mchange.com/projects/c3p0/#debugUnreturnedConnectionStackTraces。

如果这种情况立即发生,如果没有成功签出连接,那么问题是池是否曾经成功获取连接。默认情况下,如果它从未成功,则在大约 30 秒后,您的线程应该会因失败而中断。 (看起来您并没有这样做,但如果您将 acquireRetryAttempts 设置为零,c3p0 可能会无限期挂起等待连接。)

要调试 c3p0 问题,捕获 c3p0 在池初始化时转储到 INFO 级别日志的版本和配置信息会很有帮助。

祝你好运!

【讨论】:

我没有关闭底层连接,这在我的案例中是明确要求的。【参考方案2】:

此外,您似乎还没有初始化 c3p0 的 checkoutTime 参数,该参数指定客户端应等待从连接池获取连接的时间量。

见http://www.mchange.com/projects/c3p0/#checkoutTimeout

【讨论】:

【参考方案3】:

您可能需要增加 c3p0.numHelperThreads。帮助线程负责创建新的数据库连接并将它们添加到池中。如果没有足够的线程来满足需求,那么应用程序线程将在 awaitAvailable() 中等待。要确认是这种情况,请查看所有 HelperThread,看看它们是否都在使用中以及是否正在连接到数据库。

【讨论】:

以上是关于c3p0 挂在 awaitAvailable 与休眠的主要内容,如果未能解决你的问题,请参考以下文章

c3p0 连接池

c3p0 数据库连接池

c3p0 数据库连接池

c3p0连接数据库

C3P0连接池拒绝连接

C3P0连接池的使用