我正在使用Maven在Tomcat 8上开发一个Web应用程序,我使用c3p0来处理主线程和另外两个并发线程上的连接,我的连接管理器类正在询问一个DataSource单例类I& #39;已实现同步连接,如此
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次,但工作正常。
答案 0 :(得分:2)
c3p0-0.9.1.2非常非常古老;请考虑升级到0.9.5.1,即当前的生产版本。
问题既清楚又不那么清楚。明确的部分是某些东西在等待获取Connections的客户端线程上调用interrupt()
。不太清楚的部分是谁在做这件事以及为什么。
猜测是Tomcat本身就是这样做的,因为客户端线程挂起的时间太长了。如果线程挂起getConnection()
,则可能是由于连接泄漏和池耗尽造成的。我们在上面看到你如何获得Connections。你是否警惕确保它们在finally块中可靠close()
?
您可能尝试的是设置checkoutTimeout,例如
cpds.setCheckoutTimeout( 5000 ); // 5 secs
如果Connection checkout挂起,这实际上不会解决问题。但是,不是由神秘中断引发的问题,而是会看到c3p0 TimeoutExceptions。这将验证问题是否在结账时长时间挂起,这很可能是由于池泄漏,或者来自Connection泄漏(缺少对close()
的调用),或者仅仅来自maxPoolSize
值太低了你的负担。
如果确实存在连接泄漏,请参阅unreturnedConnectionTimeout和debugUnreturnedConnectionStackTraces以获取有关跟踪的帮助。另请参阅"Configuring to Debug and Workaround Broken Client Applications"