用jdbc澄清oracle中的游标

Sar*_*ins 5 java oracle jdbc resultset cursor

我遇到的情况是,我使用的第 3 方开源产品在 Oracle 中的游标用完并收到错误消息:java.sql.SQLException: ORA-01000: maximum open cursors exceeded

我的最大游标设置为 1000,我试图弄清楚达到此限制的代码是否做错了什么,或者我是否只需要增加我的限制。

经过一番调查,我在代码中发现了一个创建 ResultSet 的点,从而将我的打开游标计数增加了 1。但是,该 ResultSet 在使用后很快就关闭了......但游标计数保持不变。我能够在 3rd 方开源项目之外的简单 JDBC 应用程序中重现逻辑。

package gov.nyc.doitt.cursor;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class CursorTest {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            conn = DriverManager.getConnection("jdbc:oracle:thin:@myhost:1537:mydb", "username", "password");

            // as expected: there are 0 cursors associated with my session at this point

            ps = conn.prepareStatement("select my_column from my_table where my_id = ?");
            ps.setInt(1, 86);

            // as expected: there are 0 cursors associated with my session at this point

            rs = ps.executeQuery(); // opens 1 cursor

            // as expected: there is 1 open cursor associated with my session at this point
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            // as expected: there is 1 open cursor associated with my session at this point
            try {
                rs.close();
            } catch (SQLException e) {
                System.err.println("Unable to close rs");
            }
            // not expected: there is still 1 open cursor associated with my session at this point
            try {
                ps.close();
            } catch (SQLException e) {
                System.err.println("Unable to close simplePs");
            }
            // not expected: there is still 1 open cursor associated with my session at this point
            try {
                conn.close();
            } catch (SQLException e) {
                System.err.println("Unable to close conn");
            }
            // as expected: at this point my session is dead and so are all the associated cursors
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现一些 Oracle 文档让我认为如果关闭我们的 ResultSet 和 PreparedStatements,所有打开的游标都会关闭,但我的打开游标似乎一直在徘徊。请参阅此常见问题解答 ( http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm#1006509 ),其中说“关闭结果集或语句会释放数据库中的相应游标”。仅基于我的测试似乎没有发生,所以我一定缺乏一些基本的了解。

任何人都可以解释 Oracle 如何处理游标或向我指出一些可以启发我的文档吗?

谢谢!

Ego*_*gov 3

很久以前我就遇到过类似的问题。据我记得,问题在于延迟垃圾收集。在垃圾收集器找到并释放适当的对象之前,数据库游标不会关闭。如果频繁创建语句,您可能会遇到此问题。尝试不时手动调用垃圾收集器:

Runtime r = Runtime.getRuntime();
r.gc();
Run Code Online (Sandbox Code Playgroud)

只是为了验证这个假设。