mysql - 如何阻止c3p0连接池隐藏连接异常的原因?

标签 mysql c3p0

我有一个使用 c3p0 进行连接池的应用程序。当连接到数据库出现任何问题时,我会得到这样的异常:

java.sql.SQLException: An SQLException was provoked by the following failure: 
  com.mchange.v2.resourcepool.ResourcePoolException: A ResourcePool cannot acquire 
  a new resource -- the factory or source appears to be down.
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:62)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:531)
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
    at com.pontiflex.monitor.dao.ConnectionManager.getConfigReadOnlyDbConnection(Unknown Source)
    at com.pontiflex.monitor.dao.MonitorServiceDAO.getLiveIOCountForOrganization(Unknown Source)        at com.pontiflex.monitor.BillingMonitor.getComparisonValueForActivation(Unknown Source)
    at com.pontiflex.monitor.AbstractMonitor.isMonitoringActive(Unknown Source)
    at com.pontiflex.monitor.AbstractMonitor.generateAlerts(Unknown Source)
    at com.pontiflex.monitor.AbstractMonitor.doMonitoring(Unknown Source)
    at com.pontiflex.monitor.worker.MonitorWorker.run(Unknown Source)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Caused by: com.mchange.v2.resourcepool.ResourcePoolException: A ResourcePool cannot 
 acquire a new resource -- the factory or source appears to be down.
    at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1279)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557)
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525)
    ... 14 more

无论问题是网络连接问题、服务器问题(连接太多)还是配置问题,都会发生同样的异常。如果我打开 mysql jdbc 驱动程序和 c3p0 的调试日志记录,我将获得更多信息:

WARN  com.mchange.v2.resourcepool.BasicResourcePool  
 com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@4e074784 -- 
 Acquisition Attempt Failed!!! Clearing pending acquires. While trying 
 to acquire a needed new resource, we failed to succeed more than the 
 maximum number of allowed acquisition attempts (30). Last acquisition 
 attempt exception: 
 com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Data 
 source rejected establishment of connection,  message from server: 
 "Too many connections"
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:921)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1070)
    at com.mysql.jdbc.Connection.createNewIO(Connection.java:2775)
    at com.mysql.jdbc.Connection.<init>(Connection.java:1555)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285)
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:135)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
    at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

当 c3p0 在不调整记录器配置的情况下抛出 ResourcePoolException 时,我能做些什么来让我找到根本原因?

最佳答案

SQLException 是允许 JDBC api 抛出的(已检查的)异常,因此 c3p0 必须以通常的方式“包装”不吃 SQLExceptions 的底层异常。如果您想检查特定的内容,则对这些异常调用 getCause() 将提供原始的 Throwable。

在您引用的特定示例中,发生了一些不同的事情。问题是记录异常的线程不是您的客户端线程。 c3p0-internal 线程从数据库获取连接。您的客户端线程从池中获取连接。这两个事件在 c3p0 可以管理的范围内是分离的——这就是拥有连接池的全部意义所在。首先,内部线程执行“一轮”获取尝试(默认情况下 30 次尝试,中间有 1 秒的延迟,但您可以根据需要重新配置)。

如果获取连接的所有尝试均失败,则 c3p0 内部线程...

1) 记录失败,以及尝试时看到的最后一个异常。这是您引用的第二个异常。请注意,这是在 WARNING 级别记录的,而不是 DEBUG 级别的。如果您在 INFO 上有 c3p0 日志记录——您应该这样做——您将看到这些消息。 [如果你想看到每个单独的异常,在声明失败之前必须发生的所有 30 个异常(在默认情况下),你需要将日志记录设置为 DEBUG(或 FINE 或 ALL)。]

2) 在记录到获取系列失败后,c3p0 将中断等待()的客户端并发出 ResourcePoolException 信号,这变成了 SQLException 中的获取。这是您引用的第一个异常。发出 ResourcePoolException 信号。

3) 如果breakAfterAcquireFailure设置为 false(默认值),池将从获取失败中恢复。当新客户端进入时,它将再次尝试获取新连接。但是,如果 breakAfterAcquireFailure 设置为 true,则池将始终以异常响应新客户端请求。

无论如何,我希望这不是完全没有帮助。 c3p0 可以定义一个自定义异常类型,该类型将成为传递给客户端的包装异常的原因,因此客户端可以测试代码中的获取失败,但至少现在不会。 (对不起!)

关于mysql - 如何阻止c3p0连接池隐藏连接异常的原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15958413/

相关文章:

php - 返回超过 13578 条记录时 Doctrine 查询失败

mysql:在两列中搜索一个值并返回找到的列名

java - 在服务中构建连接池并在其他服务中使用它们

java - 无法找到 c3p0 日志消息

java c3p0 : how can i configure autoreconnect=true?

spring - 带有 HSQLDB 的 Hibernate 4.1 给出 'data exception: string data, right truncation'

mysql - "Lock wait timeout exceeded"进程列表中没有进程

python - 使用子进程导入 SQL 转储

mysql - kernel limit "open file limit "和mysql "Opened_files"相关吗?

java - 慢速 Hibernate/C3P0 处理非慢速 Postgres SELECT