我们最近发生了一次中断事件,其中应用程序线程在从c3p0检索连接时卡住了。配置集如下:
使用的c3p0版本:0.9.1.2
在正常情况下,一切正常,c3p0一直在为我们服务。但是,在最近的网络事件(网络分区 - 应用程序主机无法与数据库通信)中,我们看到应用程序无限期地试图从c3p0获取连接。
在日志中看到的Stacktrace:
Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:527)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
at amazon.identity.connection.WrappedDataSource.getConnectionWithOptionalCredentials(WrappedDataSource.java:42)
at amazon.identity.connection.LoggingDataSource.getConnectionWithOptionalCredentials(LoggingDataSource.java:55)
at amazon.identity.connection.WrappedDataSource.getConnection(WrappedDataSource.java:30)
at amazon.identity.connection.WrappedDataSource.getConnectionWithOptionalCredentials(WrappedDataSource.java:42)
at amazon.identity.connection.ConnectionProfilingDataSource.profileGetConnectionWithOptionalCredentials(ConnectionProfilingDataSource.java:118)
at amazon.identity.connection.ConnectionProfilingDataSource.getConnectionWithOptionalCredentials(ConnectionProfilingDataSource.java:99)
at amazon.identity.connection.WrappedDataSource.getConnection(WrappedDataSource.java:30)
at amazon.identity.connection.CallCountTrackingDataSource.getConnectionWithOptionalCredentials(CallCountTrackingDataSource.java:82)
at amazon.identity.connection.WrappedDataSource.getConnection(WrappedDataSource.java:30)
at com.amazon.jdbc.FailoverDataSource.doGetConnection(FailoverDataSource.java:133)
at com.amazon.jdbc.FailoverDataSource.getConnection(FailoverDataSource.java:109)
at com.amazon.identity.accessmanager.WrappedConnection$1.call(WrappedConnection.java:84)
at com.amazon.identity.accessmanager.WrappedConnection$1.call(WrappedConnection.java:82)
at com.amazon.identity.accessmanager.WrappedConnection.getConnection(WrappedConnection.java:110)
... 40 more
Caused by: com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@185e5c6b -- timeout at
awaitAvailable()
at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1317)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
....... (total of 317 such instances of prelimCheckoutResource):
中提取的一些摘录
当c3p0数据源尝试并且无法获取连接时,它将重试到acquireRetryAttempts次,每次尝试之间都会延迟acquireRetryDelay。如果所有尝试都失败,则从DataSource等待Connections的任何客户端都将看到异常,指示无法获取Connection。请注意,在完整的尝试失败之前,客户端看不到任何异常,这可能是在初始连接尝试之后的某个时间。 如果acquireRetryAttempts设置为0,则c3p0将尝试无限期地获取新的Connections,并且对getConnection()的调用可能会无限期地阻止等待成功获取。
checkoutTimeout限制客户端等待连接的时间长度,如果所有连接都已签出且无法立即提供
所以这是关于为什么会发生这种情况的理论:
网络分区存在几分钟。我假设到那时,空闲连接测试会使池中的所有活动连接无效。这意味着c3p0现在将参与获取新连接。如果任何应用程序主机尝试从池获取连接,则必须无限期地等待,直到获取连接为止(请参阅c3p0文档的摘录)。此外,checkout超时参数在这种情况下也没有帮助,因为只有在检出所有连接时才执行超时(事实并非如此)。
我的问题如下:
谢谢
答案 0 :(得分:2)
网络分区存在几分钟。我假设到那时,空闲连接测试会使池中的所有活动连接无效。这意味着c3p0现在将参与获取新连接。如果任何应用程序主机尝试从池获取连接,则必须无限期地等待,直到获取连接为止(请参阅c3p0文档的摘录)。
在这种情况下,checkout timeout参数也没有帮助,因为只有在检出所有连接时才会强制执行超时(事实并非如此)。
根据c3p0文档:在结账时#34;强制执行此超时,而不是在已经签出连接时。所以它应该对你有帮助。
checkoutTimeout 可以帮助您解决客户端超时问题,因此无需执行任何其他操作;但是我会说尝试无限期地获得连接是一个错误。我实际上使用默认的30 x 1000 ms = 30秒超时。
我还会说checkoutTimeout应该大于或等于aquire timeout(acquireRetryAttempts * acquireRetryDelay),否则第二个将适用。
答案 1 :(得分:0)
根据文档,这就是问题所在。
c3p0.acquireRetryAttempts = 0;
如果acquireRetryAttempts 为0,则C3P0 会在失败时不断尝试获取连接,每次迭代都等待10 秒(如您所配置)。
将acquireRetryAttempts 更改为一个有限值,例如10,您的等待时间将在100 秒左右,然后出现异常。