MySQL 和 JDBC 连接池:未关闭的语句

Posted

技术标签:

【中文标题】MySQL 和 JDBC 连接池:未关闭的语句【英文标题】:MySQL and JDBC Connection Pool: unclosed statements 【发布时间】:2011-07-07 09:50:03 【问题描述】:

我正在审查一大堆现有代码,试图找到可能导致连接池耗尽或抛出其他错误的未关闭连接。

在某些地方我看到连接返回到池中,ResultSet 已关闭,但 PreparedStatement 并未关闭。

在伪代码中它看起来像这样:

Connection conn = null;
try 
   conn = MyJdbcTemplateHolder.getNewConnectionFromPool();
   PreparedStatement ps = conn.prepareStatement(sql, ...);
   ResultSet rs = st.executeQuery();

   // do stuff with results

 catch(Exception e) 
   // exception
 finally 
   rs.close();
   MyJdbcTemplateHolder.returnConnectionToPool(conn);
   //***** Here is what's missing: st.close(); *****

问题是:open 语句是否会因为没有显式关闭而导致问题? 还是关闭 ResultSet 并返回连接就足够了?

显然,我不是在谈论一个开放的声明 - 我们有一个包含 100 个连接的池和代码中可能出现此问题的几十个位置。

mysql 版本为 5.1 我的 JDBC jar 是 mysql-connector-java-5.1.11-bin.jar

【问题讨论】:

【参考方案1】:

答案是是的,这可能会导致问题。正如在 SO 中讨论的那样:

Closing JDBC Connections in Pool JDBC MySql connection pooling practices to avoid exhausted connection pool

如果您在完成与连接相关的资源后(或在 finally 块中)没有以相反的顺序关闭它们,那么您将处于危险之中。连接池处理这些问题的方式各不相同,但令人担忧的是 - 至少 - 一组不正确关闭的资源被扔回池中。

如果不清楚(您可能已经知道这一点),请在此处进一步讨论正确关闭资源:

How to properly clean up JDBC resources in Java?

请注意,在即将发布的 Java 7 中,这里会有一些帮助:

http://www.javaspecialists.eu/archive/Issue190.html

其中在 Java 中引入了新的 try-with-resources 语句,该语句会自动关闭 try 语句中引用的所有 AutoCloseable 资源。

【讨论】:

+1 - 是的!简短的回答。以您打开它的相反顺序关闭所有 JDBC。永远,永远,永远。这需要是一个根深蒂固的习惯,如果你发现它没有完成,就可以改掉它。 感谢 kvista,我明白了,这就是我所害怕的……我认为在这段代码上会有很多工作要做。有谁知道由于未公开的陈述我应该期待什么样的行为?或者他们在掩护下发生了什么? 我个人的经验是数据库连接不足,因为它们没有被清理和徘徊。池会要求新的,最终数据库将不再提供。随着时间的推移,数据库最终会清理连接,但它比它们“泄漏”的速度要慢。 @Galz:我相信 - 但我不是 100% 肯定 - MySQL 连接器 J 的驱动程序(java.sql 的实现)的至少一个副作用是该语句永远不会在连接(请参阅docjar.com/src/api/com/mysql/jdbc/StatementImpl.java),这可能会阻止连接被清理/垃圾收集,并且似乎会导致内存泄漏,如果没有别的。

以上是关于MySQL 和 JDBC 连接池:未关闭的语句的主要内容,如果未能解决你的问题,请参考以下文章

如何判断mysql数据库连接池是不是连接

MySql & JDBC & 连接池 & 总结

JDBC和数据库连接池

C3P0连接池的使用

C3P0连接池的使用

C3P0连接池操作数据库