我有一个配置了100个连接的mysql数据源。即使在调用close()
之后,似乎连接也没有被释放到池中。
public void test() {
for(1 to 200) {
try {
Connection conn1 = datasource.getConnection();
ResultSet rs = conn1.createStatement().executeQuery(...);
} finally {
DBHelper.close(rs);
}
}
}
//DBHelper.java
public close(ResultSet rs) {
Statement stmt = rs.getStatement();
rs.close();
Connection conn2 = stmt.getConnection();
stmt.close();
conn2.close();
}
100之后,我从getConnection
API收到错误,表示该池为空。如果我做conn1.close()
,它就可以了。
Failed due to [http-bio-8080-exec-7] Timeout: Pool empty. Unable to fetch a connection in 180 seconds, none available[size:100; busy:100; idle:0; lastwait:180000].
我注意到conn1
的类型是com.mysql.jdbc.JDBC4Connection
,而conn2的类型是com.sun.proxy.$Proxy5
。
代码库是巨大的,所以宁愿继续这样做,因为从API的角度来看,这种关闭似乎完全没问题。是否仍然可以使用conn2
关闭连接?
操作系统:ubuntu,Tomcat 7.0.52.0。 MySQL的 - 连接器-J-20-bin.jar。
答案 0 :(得分:1)
你需要这样做:
private doClose(ResultSet rs, Connection con) throws Exception {
if (rs != null) rs.close();
if (con != null) con.close();
}
这需要是最好的做法:
public void test() {
for(1 to 200) {
Connection conn1 = null;
ResultSet rs = null;
try {
conn1 = datasource.getConnection();
rs = conn1.createStatement().executeQuery(...);
.
.
}
finally {
if (conn1 != null) conn1.close();
if (rs != null) rs.close();
}
}
}
答案 1 :(得分:0)
我真的不知道这是否有帮助,但是Tomcat围绕Connection创建了一个包装器来汇集它们:
连接池围绕实际连接创建包装器,以便正确地池化它们。我们还在这些包装器中创建拦截器以便能够执行某些功能。如果需要检索实际连接,可以使用javax.sql.PooledConnection接口执行此操作。
你可以试试这个:
Connection conn2 = stmt.getConnection();
Connection actual = ((javax.sql.PooledConnection)conn2 ).getConnection();
这是在这里陈述的(几乎在网站的末尾):https://people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html
但是这将检索真正的Connection并关闭它,以便您可以关闭池中的连接。要将其移回游泳池,可以尝试将conn2
投射到PooledConnection
并关闭该游戏。