我正在使用 c3p0 作为我的连接池。我使用的 ComboPooledDataSource 配置如下。
@Bean
public DataSource dataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("user");
dataSource.setDriverClass("oracle.jdbc.OracleDriver");
dataSource.setJdbcUrl("test");
dataSource.setPassword("test");
dataSource.setMinPoolSize("10");
dataSource.setMaxPoolSize("20");
dataSource.setMaxStatements("100");
return dataSource;
}
我在这方面遇到了一些问题。我收到警告说这可能会泄漏连接。还时不时出现以下错误,
因为所有连接都已用完。
java.sql.SQLException: Io exception: Got minus one from a read call
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:439)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
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)
并且从数据库统计中,可以看到将近 290 个非事件连接。我在两台服务器上部署了大约 8 个应用程序,
连接到同一个数据库。
我的查询是
- 如何确保连接已关闭并且不会有这么多非事件连接?
- 配置空闲时间和超时是否可以解决此问题?
- 如果服务器关闭/tomcat 关闭会发生什么情况,连接是否会保持打开状态?
- 连接主要用于启动时加载缓存,那么有没有办法在启动后不使用这些连接?
- 我应该如何处理现有的非事件连接?
最佳答案
- 给定 20 个和 8 个部署的
maxPoolSize
,您应该会看到多达 180 个连接,如果应用程序已经看到流量现在已经消退,则这些连接可能处于非事件状态。您没有配置任何内容来鼓励快速缩减您的池 -- 设置 maxIdleTime和/或 maxIdleTimeExcessConnections和/或 maxConnectionAge . - 您可能应该告诉 Spring 如何关闭您定义的数据源。在
dataSource()
方法之上单独使用@Bean(destroyMethodName="close")
而不是@Bean
。 - 您还没有配置任何类型的连接测试,因此即使断开的连接也可能保留在池中。请看Simple Advice On Connection Testing .
- 如果问题是连接泄漏,客户端最终会无限期地挂起,因为池将没有连接可 check out ,但已经达到
maxPoolSize
,因此无法 check out 从 DBMS 获取更多信息。你看到客户像这样挂了吗? 避免连接泄漏的方法是,在 Java7 之后,始终通过 try-with-resources 从数据源获取连接。 .也就是说,使用...
try ( Connection conn = myDataSource.getConnection() ) { ... }
而不是仅仅在可能抛出异常的方法中或在
try
block 中调用getConnection()
。如果您使用的是旧版本的 Java,则需要使用健壮的资源清理习惯用法,即在try
block 中获取 Connection 并确保conn.close()
总是在finally
block 中关闭,不管 finally block 中的任何其他失败。如果您不直接使用DataSource
,而是让 Spring 实用程序使用它,那么希望这些实用程序正在做正确的事情。但是您应该发布您收到的任何警告,警告您潜在的连接泄漏!- 如果您的应用程序在“预热”后对 Connections 的用处不大,并且您希望最大限度地减少资源占用,请将
minPoolSize
设置为一个非常低的数字,并使用 maxIdleTime和/或 maxIdleTimeExcessConnections和/或 maxConnectionAge如上所述,以确保在不再需要连接时池迅速缩小。或者,当您完成数据源的工作时,您可以close()
DataSource,但您可能会将其留给 Spring。
关于database - 使用 C3P0 时如何最好地关闭连接并避免非事件 session ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34389719/