Mysql数据源连接未在关闭时释放

时间:2015-05-24 10:51:46

标签: java mysql jdbc mysql-connector

我有一个配置了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。

2 个答案:

答案 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并关闭该游戏。