java - Tomcat 连接池 : few methods not releasing connection

标签 java tomcat jdbc connection-pooling

我正在使用 tomcat 连接池。但我正在关注异常 org.apache.tomcat.dbcp.dbcp.SQLNestedException:无法获取连接,池错误等待空闲对象超时

所以我在 context.xml 中添加了以下几行来查找泄漏: removeAbandoned="true"logAbandoned="true"removeAbandonedTimeout="3"

然后我开始得到以下异常 org.apache.tomcat.dbcp.dbcp.AbandonedTrace$AbandonedObjectException: DBCP object created 2015-01-17 22:12:18 by the following code was never closed: 因此,我找到了导致此泄漏的两个罪魁祸首。这两种方法具有获取连接的通用方式,即调用 unwrap 以访问特定于驱动程序的连接。

try (Connection conn = DataSourceConnectionPool.getConnection().unwrap(OracleConnection.class);
        OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall(MIGRATE_ACCOUNT)) {
        ...
        ....
)

重要的是要注意我正在使用 JDK7 的 try block ,即自动资源管理,所以我不需要 finally block 。连接关闭由 JDK 自动处理。但是为什么这个未包装的连接没有关闭。当我尝试执行以下操作时:

try (Connection poolConn = DataSourceConnectionPool.getConnection();
    Connection conn = poolConn.unwrap(OracleConnection.class);

我收到 java.sql.SQLException: Already closed. 那么如何关闭此连接。我是否必须在不使用 try block 的情况下手动完成?不应该尝试 block 句柄能够处理这个吗?

最佳答案

这是对连接池的错误使用。永远不要在未包装的连接上调用 close()

使用池连接的正常流程是

  1. 获取Connection,池获取物理连接并将其包装在自己的包装器中返回
  2. 您使用连接
  3. 您在 Connection 上调用 close()。这实际上并没有关闭任何东西,池的包装器拦截了 close() 调用并简单地将(仍处于 Activity 状态的)连接返回到池。

这是可行的,因为池有一个包装器类,比如PoolableConnection,它实现了ConnectionPoolableConnection 委托(delegate)底层连接执行实际工作,但它以不同方式实现(除其他事项外)close()。这会破坏当前的 PoolableConnection 包装器并将底层 Connection 返回到连接池。例如。

这样,您的程序逻辑就可以从DataSource 获取连接,使用Connection 然后使用close(),就像它一样将是一个正常的、未合并的 Connection

正是这种透明性使得连接池如此易于使用。

现在,当您调用 unwrap 时,PooledConnection 允许您访问它的内部、真实的 Connection 委托(delegate)。

所做的是调用 close() 委托(delegate)!

这有两个作用:

  1. 它不会在 PooledConnection 上调用 close(),因此 Connection 不会返回到池中。
  2. 它关闭了池下方的底层连接。这应该不是问题,因为池会自行处理断开的连接。

所以你需要非常小心。 始终在您从池中获得的Connection 上调用close(),将其返回到池中。 永远不要在底层连接上调用close()

所以你的代码应该是:

try (final Connection poolConn = DataSourceConnectionPool.getConnection()) {
    final Connection conn = poolConn.unwrap(OracleConnection.class);
    //do stuff with conn
    //do not close conn!!
}
//poolConn is returned to the pool

关于java - Tomcat 连接池 : few methods not releasing connection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28002176/

相关文章:

java - Android 应用程序在没有 WiFi 连接的情况下无法运行

java - Spring 4.1.6.RELEASE : @RequestParam defaultValue and required=false don't affect

java - 静态内容在项目重启之前不会更新 - Spring Boot 和 Eclipse

java - netbeans tomcat jt400链接数据库

mysql - jdbc 驱动程序 "org.gjt.mm.mysql.Driver"有什么用?

java - 如何检查 CachedRowSet 中是否存在列名?

Java Web Start 驱动安装

java - 通过 Join Table 用于子步骤的 JPA

tomcat/Liferay 没有重定向到 https 主题和 Hook

java - 使用 JDBC-ODBC 桥时是否使用了两个不同的驱动程序?