Tomcat8 + c3p0,连接中断并自动关闭

Tomcat8 + c3p0, connections are being interruped and auto closed

我正在 Tomcat 8 上使用 Maven 开发 Web 应用程序,我使用 c3p0 处理主线程和其他 2 个并发线程上的连接,我的连接管理器 class 是询问 DataSource 单例 class 我已经实现了同步连接,就像这样

public synchronized Connection getConnection() {
    try {
        return cpds.getConnection();
    } catch (SQLException ex) {
        logger.error("Error while issuing a pooled connection", ex);
    }
    return null;
}

,但是当我尝试使用这些连接时,它们开始中断

09:47:17.164 [QuartzScheduler_Worker-4] ERROR com.myapp.providers.DataSource - Error while issuing a pooled connection
java.sql.SQLException: An SQLException was provoked by the following failure: java.lang.InterruptedException
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106) ~[c3p0-0.9.1.2.jar:0.9.1.2]
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65) ~[c3p0-0.9.1.2.jar:0.9.1.2]
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:62) ~[c3p0-0.9.1.2.jar:0.9.1.2]
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:531) ~[c3p0-0.9.1.2.jar:0.9.1.2]
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128) ~[c3p0-0.9.1.2.jar:0.9.1.2]

或在交易中途关闭并破坏当时正在使用的任何语句和结果集

我正在像这样配置 DataSource 对象

cpds = new ComboPooledDataSource();
        cpds.setDriverClass(oracle.jdbc.driver.OracleDriver);
        cpds.setJdbcUrl(jdbc:oracle:thin:@xx.xxx.xxx.xxx:1521:XE);
        cpds.setUser("username");
        cpds.setPassword("password");

        // database connection properties
        cpds.setInitialPoolSize(10);
        cpds.setAcquireIncrement(3);
        cpds.setMaxPoolSize(100);
        cpds.setMinPoolSize(15);
        cpds.setMaxStatements(75);

        // connection pool preferences
        cpds.setIdleConnectionTestPeriod(60);
        cpds.setMaxIdleTime(30000);
        cpds.setAutoCommitOnClose(false);
        cpds.setPreferredTestQuery("SELECT 1 FROM DUAL");
        cpds.setTestConnectionOnCheckin(false);
        cpds.setTestConnectionOnCheckout(false);
        cpds.setAcquireRetryAttempts(30);
        cpds.setAcquireRetryDelay(1000);
        cpds.setBreakAfterAcquireFailure(false);

我也写了一个循环运行并查询数据库 n 次的小测试方法,但是工作正常。

c3p0-0.9.1.2 非常非常旧;请考虑升级到当前生产版本 0.9.5.1。

问题既清楚又不太清楚。清楚的部分是某些东西正在等待获取连接的客户端线程上调用 interrupt()。不太清楚的部分是谁在做什么以及为什么。

猜测是 Tomcat 本身正在这样做,因为客户端线程挂起时间过长。如果线程在 getConnection() 挂起,那可能是由于连接泄漏和池耗尽。我们在上面看到了您如何获取连接。您是否警惕确保它们可靠地 close()ed in finally 块?

您可以尝试设置 checkoutTimeout,例如

cpds.setCheckoutTimeout( 5000 ); // 5 secs

如果连接签出挂起,这实际上并不能解决问题。但是,您会看到 c3p0 TimeoutExceptions,而不是神秘中断引发的问题。这将验证问题是否在结帐时长时间挂起,这很可能是由于连接泄漏(缺少对 close() 的调用)或 maxPoolSize 值造成的池耗尽对你的负载来说太低了。

如果确实存在连接泄漏,请参阅 unreturnedConnectionTimeout and debugUnreturnedConnectionStackTraces for help tracking it down. See also "Configuring to Debug and Workaround Broken Client Applications"