2009-09-03 4 views
2

아래의 코드는 오라클의 열린 커서에 몇 가지 문제점을 제공합니다 (명확성을 위해 편집 됨). 기본적으로 DB에서 데이터를 선택하려고하고 반환되는 각 행에 대해 0 개 이상의 행의 하위 데이터가 선택되어 레코드에 추가됩니다. 현재 서브 데이터를 읽도록 주 데이터 세트를 채우는 동안 다른 기능을 호출하여이 작업을 수행하고 있습니다. 이는 로우 행이 1000 개 미만인 경우에 적합합니다. 사용자가 사용할 정상적인 작동 범위 인 반면, 수천 행의 순서 일 수있는 모든 행을 요청할 수 있습니다. 큰 볼륨을 선택하면 의 결과가 발생합니다. ORA-01000 : 최대 열린 커서가 오류를 초과했습니다. 코드를 실행하고 v $ open_cursors를 쿼리하면 넘어 질 때까지 커서 카운트가 올라가는 것을 볼 수 있습니다.Java가 Oracle 커서를 해제하지 않습니다.

sub 함수를 호출하는 행을 주석 처리하면 제대로 작동하지만 v $ open_cursors의 커서 개수는 몇 번씩 위아래로 변동합니다.

주 함수가 하위 함수에 연결 개체를 전달하는 것으로 나타났습니다. 코드에 의해 닫혀 있어도 연결이 열린 상태에서 결과 문과 결과 집합이 열린 상태로 유지 될 수 있다고 생각했습니다. 그래서 코드를 변경하여 각 함수가 풀에서 자체 연결을 얻고 완료되면 닫습니다. 그러나 커서와 아무런 차이가 없습니다.

나는 커서의 수를 늘릴 수 있지만, 그냥 문제를 가린다. b) 그것을 작동시키기 위해 바보처럼 높은 숫자를 고수해야한다. c) 나는 풀어주고 싶지 않다. 결함있는 코드!

그러나 커서를 놓을 코드를 얻는 방법에 대한 아이디어가 부족합니다.

+0

어떤 버전의 데이터베이스를 사용하고 있습니까? 어떤 JDBC 드라이버 (오라클?)와 어떤 버전? – APC

+0

죄송합니다. 거기에 정보가 크게 누락되었습니다. ojdbc14.jar을 사용하는 Oracle 10.2.0.1.0. – javadeveloper

답변

1

당신은 준비 시도 할 수 모두 주 ("마스터")과 서브 ("세부 사항") 문 :

PreparedStatement masterStatement = masterConnection.prepareStatement("..."); 
PreparedStatement detailStatement = detailConnection.prepareStatement("SELECT ... WHERE something = ?"); 


ResultSet masterResults = masterStatement.executeQuery(); 
while (masterResults.next()) { 
    detailStatement.setInt(1, ...); 

    ResultSet detailResults = detailStatement.executeQuery(); 
    try { 
     while (detailResults.next()) { 
     } 
    } finally { 
     detailResults.close(); 
    } 
} 
한 번에가는 하나의 연결에서 여러 결과 집합을 가진 질식 할 수
+0

이 솔루션을 중심으로 코드를 다시 작성하여 해결했습니다. 코드가 실행되는 동안 커서 카운트가 양호하고 안정적으로 유지됩니다. 답장을 보내 주셔서 감사합니다. – javadeveloper

0

Eek, 이것은 1999 년의 PowerBuilder 코드와 비슷합니다. 자식에 대해 여러 개의 선택을 수행하는 것은 반 패턴입니다. DB에 대한 호출 횟수를 줄이면이 ​​작업을 수행해야합니다. 채팅하는 방법입니다.

오라클을 사용 중이므로 부모 행이있는 하위 행을 검색하기 전에 먼저 모든 연결을 사용해보십시오. 이것이 최고의 솔루션입니다.

이전에 연결할 수 없다면 호출을 in (id1, id2, ..., idN) 절로 결합하여 청크로 검색 할 수 있습니다.

결과 집합의 동시성 설정을 살펴볼 수도 있습니다. 어쩌면 스크롤 가능한 결과 집합을 가지고 있을까요?

그러나 문제를 해결하면 VM을 날려 버리고 OOM을 얻는 것에 대해 걱정할 것입니다. 검색 결과에 행 제한이 필요합니다. 사전에

+0

아마도이 작업을 수행하는 방법을 권장해야합니다. –

+0

데이터가 사용되고 표시되는 방식 때문에 데이터를 두 개의 결과 집합으로 유지하는 것이 코딩의 관점에서 더 쉬웠습니다. 두 쿼리 모두 단순한 선택이므로 DB가 너무 많은 문제를 일으키지 않으며 50 명 미만의 사용자가 있으므로 여분의 잡담이 허용됩니다. 팁을 보내 주셔서 감사합니다. 이전에 연결을 알지 못 했으므로 나를 보면서 저를 보냈습니다. OOM 없음, 아직 큰 결과 집합에 대한 제한 시간! – javadeveloper

2

JDBC 드라이버 . 이것이 오라클의 JDBC 드라이버에서 버그가있는 행동을 일으킨다 고 생각합니다. 오라클이 분명히하지 않는 첫 번째 결과를 닫는 것만 제외하면 다른 사람들에게 문제가 발생하는 것으로 보았습니다. 머리글 행에 연결하고 모든 개체를 읽고 컬렉션에 넣은 다음 다시 반복하고 별도의 결과 집합으로 세부 개체를 읽는 것이 훨씬 낫습니다.

JDBC 사양에는 이와 관련하여 JDBC 드라이버에 대한 의무가 명시되어 있지 않지만 JDBC-ODBC 브리지는 연결 당 하나의 활성 문만 명시 적으로 허용하므로 다른 JDBC 드라이버는 자유롭게 유사한 제한을 설정할 수 있습니다 연결 당 하나의 열린 결과 세트로).

0

연결 풀을 사용하고 있습니까? 일부 PreparedStatements를 닫을 때 캐시 될 수 있습니다.

이 경우 있는지 확인하려면 임시로 준비되지 않은 명령문을 사용하거나 연결 풀을 비활성화하십시오.