【问题标题】:How best to close connections and avoid inactive sessions while using C3P0?使用 C3P0 时如何最好地关闭连接并避免非活动会话?
【发布时间】:2015-12-21 05:55:21
【问题描述】:

我正在使用 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. 我应该如何处理现有的非活动连接?

【问题讨论】:

    标签: database spring jpa connection-pooling c3p0


    【解决方案1】:
    • 鉴于maxPoolSize 有 20 个和 8 个部署,您应该会看到多达 180 个连接,如果应用程序已经看到现在已经消退的流量时段,这些连接可能会处于非活动状态。您没有进行任何配置来鼓励快速缩减池 - 设置 maxIdleTime 和/或 maxIdleTimeExcessConnections 和/或 maxConnectionAge
    • 您可能应该告诉 Spring 如何关闭您定义的 DataSource。在 dataSource() 方法上方单独使用 @Bean(destroyMethodName="close") 而不是 @Bean
    • 您尚未配置任何类型的连接测试,因此即使断开的连接也可能保留在池中。请参阅Simple Advice On Connection Testing
    • 如果问题是连接泄漏,客户端最终将无限期挂起,因为池将没有连接来检查,但已经达到maxPoolSize,因此无法从数据库管理系统。您是否看到客户这样挂起?
    • 避免连接泄漏的方法是,在 Java7 之后,始终通过 try-with-resources 从数据源获取连接。也就是说,使用...

      try ( Connection conn = myDataSource.getConnection() ) {
        ...
      }
      

      而不仅仅是在可能引发异常的方法或try 块中调用getConnection()。如果您使用的是旧版本的 Java,则需要使用健壮的资源清理习语,即在 try 块中获取 Connection 并确保 conn.close() 始终在 finally 块中关闭,无论finally 块中的任何其他故障。如果您没有直接使用DataSource,而是让 Spring 实用程序使用它,希望这些实用程序做的是正确的事情。但是您应该发布收到的任何警告,警告您可能存在连接泄漏!

    • 如果您的应用程序在“热身”后很少使用 Connections,并且您希望最小化资源占用,请将minPoolSize 设置为非常低的数字,并使用maxIdleTime 和/或maxIdleTimeExcessConnections 和/ 或 maxConnectionAge 如上所述,以确保当不再需要连接时,池迅速缩小。或者,您可以在完成其工作后 close() DataSource,但您可能会将其留给 Spring。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      • 2018-07-07
      • 1970-01-01
      相关资源
      最近更新 更多