database - 使用 C3P0 时如何最好地关闭连接并避免非事件 session ?

标签 database spring jpa connection-pooling c3p0

我正在使用 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 个应用程序,

连接到同一个数据库。

我的查询是

  1. 如何确保连接已关闭并且不会有这么多非事件连接?
  2. 配置空闲时间和超时是否可以解决此问题?
  3. 如果服务器关闭/tomcat 关闭会发生什么情况,连接是否会保持打开状态?
  4. 连接主要用于启动时加载缓存,那么有没有办法在启动后不使用这些连接?
  5. 我应该如何处理现有的非事件连接?

最佳答案

  • 给定 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/

相关文章:

java - Hibernate - 在运行时更改连接字符串

sql - Oracle Sql获取另一列的每个不同值出现次数最多的值

c# - 更新条目时出错。有关详细信息,请参阅内部异常

database - Postgres数据库备份错误-密码中的特殊字符

spring - 使用 Spring 注入(inject)和服务的 HTTPSessionListener => 无法访问我的 bean

java - 如何将对象作为 URI 行中的查询参数传递?

java - Spring 注入(inject)使用静态方法调用的实例创建的对象

jakarta-ee - 过滤器不初始化 EntityManager

java - 如何使用 JPA 检索多个对象?

java - 无法持久化对象