关闭 ResultSet 但不关闭 PreparedStatement
Closing ResultSet but not closing PreparedStatement
如果 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,jdbc11.2.0.3
谢谢
请尝试回答我的问题,不要专注于修复
What type of resource leak can I expect if ResultSet is closed, but
PreparedStatement not ?
泄漏将是最大打开游标问题。
ORA-01000: maximum open cursors exceeded
如果超过最大打开游标数,数据库将变得不可用,除了已经持有的游标。但是,大多数情况下发生这种情况时,甚至不会使用保持的游标(您的问题就是这种情况)。
自 java 7 以来,处理此问题的最佳方法是使用 try with ressources。 ResultSet
和 PreparedStatement
都实现了 AutoCloseable
接口,这意味着它们将在不再需要时关闭。
如果您没有 java 7,则需要在 finally
块中处理此问题,但请确保在关闭之前验证空值,否则您可能会遇到 NPE,如果资源从未初始化。
请注意,反向操作不会造成任何问题,因为关闭语句会自动关闭它的结果集。
请注意,您可以轻松地为您的应用程序允许更多游标,以减少超过最大值的可能性。
ALTER SYSTEM SET open_cursors = 400 SCOPE=BOTH;
但是,大多数情况下,如果遇到最大打开游标,这不应该是解决方案,因为它只会隐藏真正的问题。
可能在 Oracle 中,您不会在数据库服务器端冒太多风险。准备好的语句在库缓存中共享,当语句不被执行时,Oracle 可以摆脱它。
但不管怎么说这是个很不好的习惯。 JDBC driver side. 上发生的事情也值得怀疑
这是 OCI 文档的摘录,但我认为 JDBC 行为将是相似的:
Statement Caching without Session Pooling in OCI
Users perform the usual OCI steps to logon. The call to obtain a
session will have a mode that specifies whether statement caching is
enabled for the session. Initially the statement cache will be empty.
Developers will try to find a statement in the cache using the
statement text. If the statement exists the API will return a
previously prepared statement handle, otherwise it will return a newly
prepared statement handle.
因此,当在客户端使用 PreparedStatement 缓存时,看起来 Oracle 甚至可以避免软解析。因此,当您不关闭 PreparedStamement 时,您可能会遇到此缓存问题。
注意:映射是 RecultSet => "open cursor",而 PreparedStatement 可能映射到库缓存中的条目。对于 Oracle,关闭 ResultSet 是至关重要的。
PS:与 Informix(PostgreSQL 和其他 RDBMS)相反,执行计划不共享,每个会话 process/thread 都有自己的准备好的语句集。因此,当使用其他数据库时,您可能会遇到严重的麻烦。
如果 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,jdbc11.2.0.3
谢谢
请尝试回答我的问题,不要专注于修复
What type of resource leak can I expect if ResultSet is closed, but PreparedStatement not ?
泄漏将是最大打开游标问题。
ORA-01000: maximum open cursors exceeded
如果超过最大打开游标数,数据库将变得不可用,除了已经持有的游标。但是,大多数情况下发生这种情况时,甚至不会使用保持的游标(您的问题就是这种情况)。
自 java 7 以来,处理此问题的最佳方法是使用 try with ressources。 ResultSet
和 PreparedStatement
都实现了 AutoCloseable
接口,这意味着它们将在不再需要时关闭。
如果您没有 java 7,则需要在 finally
块中处理此问题,但请确保在关闭之前验证空值,否则您可能会遇到 NPE,如果资源从未初始化。
请注意,反向操作不会造成任何问题,因为关闭语句会自动关闭它的结果集。
请注意,您可以轻松地为您的应用程序允许更多游标,以减少超过最大值的可能性。
ALTER SYSTEM SET open_cursors = 400 SCOPE=BOTH;
但是,大多数情况下,如果遇到最大打开游标,这不应该是解决方案,因为它只会隐藏真正的问题。
可能在 Oracle 中,您不会在数据库服务器端冒太多风险。准备好的语句在库缓存中共享,当语句不被执行时,Oracle 可以摆脱它。
但不管怎么说这是个很不好的习惯。 JDBC driver side. 上发生的事情也值得怀疑 这是 OCI 文档的摘录,但我认为 JDBC 行为将是相似的:
Statement Caching without Session Pooling in OCI
Users perform the usual OCI steps to logon. The call to obtain a session will have a mode that specifies whether statement caching is enabled for the session. Initially the statement cache will be empty. Developers will try to find a statement in the cache using the statement text. If the statement exists the API will return a previously prepared statement handle, otherwise it will return a newly prepared statement handle.
因此,当在客户端使用 PreparedStatement 缓存时,看起来 Oracle 甚至可以避免软解析。因此,当您不关闭 PreparedStamement 时,您可能会遇到此缓存问题。
注意:映射是 RecultSet => "open cursor",而 PreparedStatement 可能映射到库缓存中的条目。对于 Oracle,关闭 ResultSet 是至关重要的。
PS:与 Informix(PostgreSQL 和其他 RDBMS)相反,执行计划不共享,每个会话 process/thread 都有自己的准备好的语句集。因此,当使用其他数据库时,您可能会遇到严重的麻烦。