DBCP返回已关闭的连接 [英] DBCP returns closed connections
问题描述
我们看到来自 org.apache.commons.dbcp.BasicDataSource
的数据库连接因套接字写错误而死的情况:
We are seeing situations where our database connection from org.apache.commons.dbcp.BasicDataSource
is dying with socket write errors:
com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: socket write error
所有后续写入连接的尝试都失败了,当然:
All subsequent attempts to write to the connection fail, of course:
com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
更新代码以捕获此类异常并在发生新请求时请求新连接后再次失败。我是否正确怀疑调用 DataSource#getConnection()
实际上每次调用时都没有提供新连接?是不是只是重用现有的连接,这是关闭的?
After updating the code to catch such exceptions and request a new connection when it occurs, it failed again. Am I correct in suspecting that calling DataSource#getConnection()
is not actually giving a new connection each time it is called? Isn't it just reusing the existing connection, which is closed?
如果我是正确的,什么是丢弃旧连接并请求新连接的正确方法?
If I am correct, what is the right way to throw away the old connection and request a new one?
编辑:这是我想知道的更为简洁的版本:
Here's a more succint version of what I'd like to know:
Connection c1, c2;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c2 = DatabaseManager.getConnection();
c1 == c2是真的陈述吗?或者分配了两个连接?如果是后者,那么像这样的代码表示连接池泄漏:
Is "c1 == c2" a true statement? Or have two connections been allocated? And if it's the latter, would code like this represent a "connection pool leak":
Connection c1;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c1 = DatabaseManager.getConnection();
推荐答案
数据库已关闭池化连接。这可能意味着两件事:
The pooled connection has been closed by the DB. That can mean 2 things:
- 连接池保持连接打开时间过长。
- 数据库在太短的时间后关闭连接。
理论上,增加/减少任何一方的超时以对齐它应解决问题。
In theory, increasing/decreasing the timeout on either sides to align it should fix the problem.
在DBCP上,最好的办法是在返回之前验证连接 testOnBorrow = true
和 validationQuery
设置,例如 SELECT 1
。您可以在 Tomcat JDBC数据源文档<中找到配置选项/ a>。
On DBCP, your best bet is to validate connections before returning by a testOnBorrow=true
and a validationQuery
setting, e.g. SELECT 1
. You can find configuration options in the Tomcat JDBC data sources documentation.
更新根据您的更新:
这是我想知道的更多简洁版本:
Here's a more succint version of what I'd like to know:
Connection c1, c2;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c2 = DatabaseManager.getConnection();
c1 == c2是真的陈述吗?或者分配了两个连接?
Is "c1 == c2" a true statement? Or have two connections been allocated?
这是两个截然不同的连接。只有当您调用 c1.close()
时, c2
才有可能返回相同的连接。
It are two distinct connections. Only if you call c1.close()
then there's a reasonable chance that c2
returns the same connection.
如果是后者,那么这样的代码就代表了连接池泄漏:
And if it's the latter, would code like this represent a "connection pool leak":
Connection c1;
c1 = DatabaseManager.getConnection();
// c1.close() not called
c1 = DatabaseManager.getConnection();
是的,肯定会泄漏第一个连接,因为它从来没有回到了游泳池。您应该始终在 try-finally
块中以尽可能短的范围关闭所有数据库资源。然而,有点像样的连接池可以配置以获得废弃的连接,但这绝对不能用作解决方法。
Yes, definitely it will leak the first connection as it's never been returned to the pool. You should always close all DB resources in the shortest possible scope in a try-finally
block. A bit decent connection pool is however configureable to reap abandoned connections, but this should definitely not be used as "workaround".
这篇关于DBCP返回已关闭的连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!