2009-12-14 3 views
4

사용중인 타사 오픈 소스 제품에서 Oracle에서 커서가 부족하여 다음과 같은 오류가 발생하는 경우가 있습니다. java.sql.SQLException : ORA-01000 : 최대 열린 커서가jdbc를 사용하여 oracle에서 커서를 명확하게 함

을 초과했습니다.

최대 커서가 1000으로 설정되어 있으며이 제한에 도달 한 코드가 잘못 처리하고 있는지 또는 제한을 단순히 늘려야하는지 파악하려고합니다.

몇 가지 조사가 끝나면 ResultSet이 생성되어 열린 커서 수를 1 씩 늘리는 코드를 발견했습니다. 그러나 ResultSet은 사용 후 곧 닫힙니다. 그러나 커서 수는 그대로 유지됩니다. 입니다. 제 3 자 오픈 소스 프로젝트 외부의 간단한 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)를 참조하십시오. 일어날 것 같지 않은 나의 시험에 기초를 두어서만, 그래서 나는 약간 기본적인 이해가 결여되고 있어야합니다.

오라클이 커서를 처리하는 방법을 설명하거나 나에게 계몽적 인 문서를 알려줄 수 있습니까?

감사합니다.

+0

코드가 멋지다고 생각됩니다. 오라클 자체에서 제공하는 드라이버를 사용하고 있습니까? – Rajat

+0

코드가 완벽하게 정상적으로 보입니다. –

답변

3

아주 오래 전 비슷한 문제가 발생했습니다. 지금까지 내가 기억하는 한, 문제는 가비지 수집이 지연되었습니다. 가비지 수집기가 적절한 개체를 찾아 릴리스 할 때까지 데이터베이스 커서가 닫히지 않습니다. 명령문을 자주 작성하면이 문제가 발생할 수 있습니다. 수동으로 가비지 수집기를 수동으로 호출하십시오.

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

이 가정을 검사하기 만하면됩니다.

+1

PreparedStatement 및 ResultSet 논리를 모두 별도의 메소드로 이동하면 PreparedStatement 및 ResultsSet이 닫힌 후 커서가 닫히기 전에 (즉, 일단 범위를 벗어난 경우) 커서가 사라집니다. 감사! –

+0

사용 된 JDBC 드라이버의 버그와 비슷합니다. 가능한 경우, JDBC 드라이버를 사용 가능한 최신 호환 버전으로 업그레이드하십시오. 이는 구현 특정 (mis) 동작에 맞도록 JDBC 코딩을 변경하는 것보다 선호됩니다. – BalusC

+0

최신 드라이버를 사용하고 있습니다. 이 코드는 작동 방식을 이해하는 데 도움이되는 테스트 코드이므로 아무 것도 수용 할 수 있도록 코딩을 변경하지 않았습니다. –

관련 문제