如果关闭ResultSet,我可以预期哪种类型的资源泄漏,但PreparedStatement不会。它非常可疑,它可能会导致游标打开...
PreparedStatement p = connection.prepareStatement(...);
try {
ResultSet r = p.executeQuery();
try {
while (r.next()) {
....
}
} finally {
try {
r.close();
} catch (SQLException e) {
// log this or something -- prevent these from masking original exception
}
}
}
是Oracle 11g,jdbc 11.2.0.3
由于
Plz尝试回答我的问题,而不是专注于修复
答案 0 :(得分:4)
如果关闭ResultSet,我可以期待什么类型的资源泄漏,但是 PreparedStatement不是吗?
泄漏将是最大的开放光标问题。
ORA-01000: maximum open cursors exceeded
如果超出最大打开游标数,则数据库将变为不可用,但已保留的游标除外。但是,大多数时候发生这种情况时,所使用的游标甚至都没有使用(在你的问题中就是这种情况)。
从java 7开始,处理此问题的最佳方法是使用try with ressources。 ResultSet
和PreparedStatement
都会实现AutoCloseable
接口,这意味着它们将在不再需要时关闭。
如果您没有java 7,那么您需要在finally
块中处理此问题,但请确保在关闭之前验证空值,否则如果从未初始化ressource,则可能会遇到NPE。 / p>
请注意,反向不会导致任何问题,因为关闭语句会自动关闭结果集。
请注意,您可以轻松地为应用程序添加更多游标,以减少超出最大值的可能性。
ALTER SYSTEM SET open_cursors = 400 SCOPE=BOTH;
但是,大多数情况下,如果遇到最大打开游标,这不应该是一个解决方案,因为它只会隐藏真正的问题。
答案 1 :(得分:1)
可能在Oracle中,您不会在数据库服务器端冒太多风险。准备好的语句在库缓存中共享,当语句没有被执行时,Oracle可以摆脱它。
但无论如何这是非常糟糕的习惯。在JDBC driver side.上发生的事情也值得怀疑 这是OCI文档的摘录,但我认为JDBC行为类似:
OCI中没有会话池的语句缓存
用户执行通常的OCI步骤进行登录。要求获得一个 session将有一个指定语句缓存是否的模式 已启用会话。最初语句缓存将为空。 开发人员将尝试使用缓存在缓存中查找语句 声明文本。如果该语句存在,则API将返回a 以前准备好的语句句柄,否则会重新返回 准备好的陈述句柄。
因此,当客户端使用PreparedStatement缓存时,Oracle似乎可以避免软解析。因此,当您不关闭PreparedStamement时,您可能会遇到此缓存问题。
注意:映射是RecultSet => “open cursor”,而PreparedStatement可能映射到Library缓存中的一个条目。对于Oracle,关闭ResultSet是至关重要的。
PS:相反,在Informix(PostgreSQL和其他RDBMS)上,执行计划不会被共享,并且每个会话进程/线程都拥有它自己的一组预准备语句。因此,当使用其他数据库时,您可能会遇到严重问题。