5

私が使用しているサード パーティのオープン ソース製品が Oracle でカーソルを使い果たし、次のエラーを受け取る状況があります: java.sql.SQLException: ORA-01000: 最大オープン カーソルを超えました

最大カーソル数が 1000 に設定されており、この制限に達しているコードが何か間違ったことを行っているのか、単に制限を増やす必要があるのか​​を調べようとしています。

調査の結果、ResultSet が作成されるコード内のポイントを見つけたため、開いているカーソルの数が 1 増えました。ただし、その ResultSet は使用後すぐに閉じられます....しかし、カーソルの数はそのままです。サードパーティのオープン ソース プロジェクト以外の単純な 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
        }
    }
}

ResultSet と PreparedStatements を閉じると開いているカーソルがすべて閉じられると思わせる Oracle のドキュメントをいくつか見つけましたが、開いているカーソルがぶら下がっているようです。この FAQ ( http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm#1006509 ) を参照してください。「結果セットまたはステートメントを閉じると、データベース内の対応するカーソルが解放されます。」起こらないと思われる私のテストに基づいているだけなので、基本的な理解が欠けているに違いありません。

Oracleがカーソルを処理する方法を説明したり、私を啓発するドキュメントを教えてもらえますか?

ありがとう!

4

1 に答える 1

3

かなり前に、私は同様の問題に遭遇しました。私が覚えている限り、問題はガベージ コレクションの遅延にありました。データベース カーソルは、ガベージ コレクターが適切なオブジェクトを見つけて解放するまで閉じません。ステートメントが頻繁に作成される場合、この問題が発生する可能性があります。時々、ガベージ コレクターを手動で呼び出すようにしてください。

Runtime r = Runtime.getRuntime();
r.gc();

この仮定を確認するだけです。

于 2009-12-14T20:03:06.113 に答える