уточнение курсоров в оракуле с помощью jdbc - PullRequest
4 голосов
/ 14 декабря 2009

У меня есть ситуация, когда в стороннем продукте с открытым исходным кодом, который я использую, не хватает курсоров в 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
        }
    }
}

Я нашел некоторую документацию Oracle, которая заставила меня думать, что все открытые курсоры будут закрыты, если вы закроете наши ResultSet и PreparedStatements, но мои открытые курсоры, кажется, зависают. См. Этот раздел часто задаваемых вопросов (http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm#1006509), который гласит: «Закрытие набора результатов или оператора освобождает соответствующий курсор в базе данных.» Только на основе моего теста, который, по-видимому, не выполняется, поэтому мне не хватает базовых знаний.

Может кто-нибудь объяснить, как Oracle обрабатывает курсоры, или указать мне какую-нибудь документацию, которая меня просветит?

Спасибо!

1 Ответ

3 голосов
/ 14 декабря 2009

Давным-давно я столкнулся с подобной проблемой. Насколько я помню, проблема была в отложенной сборке мусора. Курсор базы данных не закроется, пока сборщик мусора не найдет и не освободит соответствующий объект. Если заявления создаются часто, вы можете столкнуться с этой проблемой. Попробуйте время от времени вызывать сборщик мусора вручную:

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

просто чтобы проверить это предположение.

...