c3p0连接结账需要15分钟才能失败

时间:2015-04-24 08:31:55

标签: oracle connection-pooling c3p0

使用c3p0遇到问题。在大多数情况下工作正常,但在防火墙后面的prod环境中,偶尔无法检查连接。问题是识别连接不可用需要15分钟。由于其他连接正在检查中并且在15分钟的间隔期间愉快地使用,因此该池不会耗尽。

日志:

23 Apr 2015 09:08:16.426 [EventProcessor-1] DEBUG c.m.v.c.i.C3P0PooledConnectionPool - Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@5a886282] on CHECKOUT.

15分钟后:

23 Apr 2015 09:23:43.073 [EventProcessor-1] DEBUG c.m.v.c.i.C3P0PooledConnectionPool - Test of PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@5a886282] on CHECKOUT has FAILED. 
java.sql.SQLException: Connection is invalid
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:572) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.finerLoggingTestPooledConnection(C3P0PooledConnectionPool.java:451) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.finerLoggingTestPooledConnection(C3P0PooledConnectionPool.java:443) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishResourceOnCheckout(C3P0PooledConnectionPool.java:336) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.resourcepool.BasicResourcePool.attemptRefurbishResourceOnCheckout(BasicResourcePool.java:1727) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:553) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutAndMarkConnectionInUse(C3P0PooledConnectionPool.java:756) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:683) [c3p0-0.9.5.jar:0.9.5]
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:140) [c3p0-0.9.5.jar:0.9.5]

然后再增加一些日志:

23 Apr 2015 09:23:43.073 [EventProcessor-1] DEBUG c.m.v.r.BasicResourcePool - A resource could not be refurbished for checkout. [com.mchange.v2.c3p0.impl.NewPooledConnection@5a886282] 
java.sql.SQLException: Connection is invalid
...
23 Apr 2015 09:23:43.074 [EventProcessor-1] DEBUG c.m.v.r.BasicResourcePool - Resource [com.mchange.v2.c3p0.impl.NewPooledConnection@5a886282] could not be refurbished in preparation for checkout. Will try to find a better resource. 
23 Apr 2015 09:23:43.074 [C3P0PooledConnectionPoolManager[identityToken->67oy4j981qzvkd716hgow4|4177fc5c]-HelperThread-#2] DEBUG c.m.v.r.BasicResourcePool - Preparing to destroy resource: com.mchange.v2.c3p0.impl.NewPooledConnection@5a886282 
23 Apr 2015 09:23:43.074 [EventProcessor-1] DEBUG c.m.v.c.i.C3P0PooledConnectionPool - Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@41318736] on CHECKOUT. 
23 Apr 2015 09:23:43.074 [C3P0PooledConnectionPoolManager[identityToken->67oy4j981qzvkd716hgow4|4177fc5c]-HelperThread-#2] DEBUG c.m.v.c.i.C3P0PooledConnectionPool - Preparing to destroy PooledConnection: com.mchange.v2.c3p0.impl.NewPooledConnection@5a886282 
23 Apr 2015 09:23:43.076 [C3P0PooledConnectionPoolManager[identityToken->67oy4j981qzvkd716hgow4|4177fc5c]-HelperThread-#2] DEBUG c.m.v.c3p0.impl.NewPooledConnection - Failed to close physical Connection: oracle.jdbc.driver.T4CConnection@25145762 
java.sql.SQLRecoverableException: IO Error: Broken pipe
    at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:612) ~[ojdbc6_g-11.2.0.1.0.jar:11.2.0.1.0]
    at oracle.jdbc.driver.PhysicalConnection.close(PhysicalConnection.java:5094) ~[ojdbc6_g-11.2.0.1.0.jar:11.2.0.1.0]
    at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:642) [c3p0-0.9.5.jar:0.9.5]

c3p0配置:

        ComboPooledDataSource ods = new ComboPooledDataSource();
...
        ods.setInitialPoolSize(5);
        ods.setMinPoolSize(5);
        ods.setMaxPoolSize(10);
        ods.setMaxStatements(50);

        ods.setTestConnectionOnCheckout(true);

所以没什么异国情调。我知道连接丢失是可能的,因此在结账时测试连接。任何想法为什么需要这么长时间来验证/失败连接?我们正在使用Oracle数据库。 感谢。

2 个答案:

答案 0 :(得分:2)

首先,我假设您已验证日志消息之间没有该Connection的签出。显然,你会期待许多消息,比如......

Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@5a886282] on CHECKOUT.

...在失败前的最后一条消息之前。很多这些消息会更早出现。理想情况下,只有失败前的最终信息应该比你看到的15分钟更接近故障的检测。

假设这是最终的消息,那么问题就与你的Connections如何死亡有关。 c3p0运行测试,然后等待成功完成或异常。如果您的Connection以某种方式死亡,连接测试只挂了15分钟,那么你可能会看到你所看到的。

以下是一些建议。

  1. 使用c3p0的idleConnectionTestPeriod可以在客户端结帐之前理想地检测这些故障,这样客户就不太可能遇到长时间挂起。 (您也可以在办理登机手续时进行测试。)
  2. 弄清楚正在运行什么样的连接测试。您正在使用c3p0 0.9.5,因此如果您的驱动程序支持它,则默认测试是对Connection.isValid()的调用,该调用应该很快。我没有在任何日志中看到你引用了实际测试失败的堆栈跟踪(也许它是一个截断的根本原因Exception?它肯定会被一个名为{{1}的记录器记录在FINER / DEBUG级别验证(从堆栈跟踪)您的驱动程序正在使用快速com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool连接测试而不是c3p0的慢速默认连接测试。如果不是(可能是因为您的驱动程序不支持),请考虑设置快速isValid()
  3. 您可以尝试maxAdministrativeTaskTime,但只有挂起连接测试的任何内容响应中断()调用,这才有可能真正有用。
  4. 无论如何,我希望这不是完全无用的!

答案 1 :(得分:1)

看起来这是一种情况,当防火墙终止连接时,根本没有发回任何响应,甚至是没有数据的TCP ACK。在这种情况下,验证连接的查询将永远不会返回。这是在socket / jdbc驱动程序级别上。

解决方案:

  • 找出防火墙断开连接策略(在我们的情况下为1小时)
  • 设置 c3p0.maxConnectionAge 属性以强制c3p0每隔X秒重新连接一次。