DBCP返回关闭的连接
问题内容:
我们看到的情况是,我们的数据库连接由于org.apache.commons.dbcp.BasicDataSource
套接字写入错误而终止:
com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: socket write error
当然,所有随后的写入连接的尝试都会失败:
com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
在更新代码以捕获此类异常并在发生连接时请求新连接后,该连接再次失败。我是否怀疑DataSource#getConnection()
每次调用实际上都不在提供新的连接?难道不只是重用已关闭的现有连接吗?
如果我是正确的,那么丢弃旧的连接并请求新的连接的正确方法是什么?
编辑:这是我想知道的更简洁的版本:
Connection c1, c2;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c2 = DatabaseManager.getConnection();
“ c1 == c2”是正确的说法吗?还是分配了两个连接?如果是后者,则将这样的代码表示“连接池泄漏”:
Connection c1;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c1 = DatabaseManager.getConnection();
问题答案:
池连接已被数据库关闭。这可能意味着两件事:
- 连接池使连接打开时间过长。
- DB在过短的时间后关闭连接。
从理论上讲,增加/减少双方的超时以使其一致可以解决该问题。
在DBCP上,最好的选择是在通过testOnBorrow=true
和validationQuery
设置返回之前验证连接,例如SELECT 1
。您可以在Tomcat JDBC数据源文档中找到配置选项。
更新 按照您的更新:
这是我想知道的更简洁的版本:
Connection c1, c2; c1 = DatabaseManager.getConnection(); // c1.close() not called c2 = DatabaseManager.getConnection();
“ c1 == c2”是正确的说法吗?还是分配了两个连接?
这是两个不同的连接。仅当您致电时,c1.close()
才有可能c2
返回相同的连接。
如果是后者,则将这样的代码表示“连接池泄漏”:
Connection c1; c1 = DatabaseManager.getConnection(); // c1.close() not called c1 = DatabaseManager.getConnection();
是的,因为它永远不会返回到池中,因此肯定会泄漏第一个连接。您应该 始终 在一个try- finally
块中以尽可能短的范围关闭所有数据库资源。但是,可以配置一些不错的连接池以获取废弃的连接,但是,绝对不应该将其用作“替代方法”。