programing

java.sql.SQLException: - ORA-01000: 열려 있는 최대 커서 수를 초과했습니다.

goodcopy 2022. 11. 26. 13:04
반응형

java.sql.SQLException: - ORA-01000: 열려 있는 최대 커서 수를 초과했습니다.

ORA-01000 SQL 예외가 발생하였습니다.그래서 그것과 관련하여 몇 가지 질문이 있습니다.

  1. 열려 있는 최대 커서가 JDBC 연결 수와 정확히 관련되어 있습니까?아니면 단일 연결에 대해 작성한 문 및 결과 집합 개체와도 관련되어 있습니까? (연결 풀을 사용하고 있습니다.
  2. 데이터베이스 내의 스테이트먼트/결과셋 객체의 수(접속 등)를 설정하는 방법이 있습니까?
  3. 단일 스레드 환경에서 메서드 local statement/resultset 객체가 아닌 instance variable statement/resultset 객체를 사용하는 것이 좋습니까?
  4. 루프에서 준비된 문을 실행하면 이 문제가 발생합니까? (물론 sqlBatch를 사용할 수도 있습니다.) 주의: pStmt는 루프가 종료되면 닫힙니다.

    { //method try starts  
      String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
      pStmt = obj.getConnection().prepareStatement(sql);
      pStmt.setLong(1, subscriberID);
      for (String language : additionalLangs) {
        pStmt.setInt(2, Integer.parseInt(language));
        pStmt.execute();
      }
    } //method/try ends
    
    { //finally starts
       pStmt.close()
    } //finally ends 
    
  5. conn.createStatement()와 conn.prepareStatement(sql)가 단일 연결 개체로 여러 번 호출되면 어떻게 됩니까?

편집 1: 6.Weak/Soft 참조문 개체를 사용하면 누출을 방지하는 데 도움이 됩니까?

편집 2: 1제 프로젝트에서 누락된 "statement.close"를 모두 찾을 수 있는 방법은 없습니까?메모리 누수는 아닌 것으로 알고 있습니다.하지만 가비지 컬렉션에 적합한 스테이트먼트 참조(close()가 실행되지 않는 경우)를 찾아야 합니다.사용 가능한 툴이 있습니까?아니면 수동으로 분석해야 하나요?

이해 좀 시켜주세요.

솔루션

사용자 이름 -VELU에 대해 오라클 DB에서 열린 커서를 찾으려면 다음과 같이 하십시오.

ORACLE 시스템으로 이동하여 sysdba로 sqlplus를 시작합니다.

[oracle@db01 ~]$ sqlplus / as sysdba 

그럼 달려라

SELECT   A.VALUE,
    S.USERNAME,
    S.SID,
    S.SERIAL#
  FROM V$SESSTAT A,
    V$STATNAME B,
    V$SESSION S
  WHERE A.STATISTIC# = B.STATISTIC#
    AND S.SID        = A.SID
    AND B.NAME       = 'opened cursors current'
    AND USERNAME     = 'VELU';

가능하다면 제 답변을 읽고 솔루션에 대해 좀 더 이해해주세요.

ORA-01000은 Oracle 데이터베이스 개발에서 매우 일반적인 오류입니다.Java의 경우 응용 프로그램이 데이터베이스 인스턴스에 구성된 커서 수보다 더 많은 ResultSet을 열려고 시도할 때 발생합니다.

일반적인 원인은 다음과 같습니다.

  1. 설정 오류

    • DB의 커서보다 더 많은 수의 스레드가 데이터베이스에 질의합니다.한 가지 예로, 연결 및 스레드 풀이 데이터베이스의 커서 수보다 큰 경우를 들 수 있습니다.
    • 동일한 DB 인스턴스(많은 스키마를 포함)에 연결된 개발자 또는 애플리케이션이 여러 개 있고 함께 너무 많은 연결을 사용하고 있습니다.
    • 솔루션:

  2. 커서 누수

    • 응용 프로그램이 결과 세트(JDBC) 또는 커서(데이터베이스의 저장 프로시저)를 닫지 않습니다.
    • 솔루션:커서 누수는 버그입니다. DB의 커서 수를 늘리면 불가피한 오류가 지연될 뿐입니다.누수는 정적 코드 분석, JDBC 또는 응용 프로그램레벨 로깅 및 데이터베이스 모니터링을 사용하여 검출할 수 있습니다.

배경

이 절에서는 커서 뒤에 있는 일부 이론과 JDBC 사용 방법에 대해 설명합니다.배경을 알 필요가 없다면 생략하고 '누수 제거'로 바로 이동할 수 있습니다.

커서가 뭐죠?

커서는 쿼리 상태, 특히 ResultSet에서 판독기가 있는 위치를 유지하는 데이터베이스의 리소스입니다.각 SELECT 문에는 커서가 있으며 PL/SQL 저장 프로시저는 필요한 만큼의 커서를 열고 사용할 수 있습니다.커서에 대한 자세한 내용은 Orafaq에서 확인할 수 있습니다.

데이터베이스 인스턴스는 일반적으로 여러 개의 서로 다른 스키마를 제공하며 각각 여러 개의 세션이 있는 여러 다른 사용자를 처리합니다.이를 위해 모든 스키마, 사용자 및 세션에 사용할 수 있는 커서의 수가 고정되어 있습니다.모든 커서가 열려 있고(사용 중) 새 커서가 필요한 요청이 들어오면 요청이 실패하고 ORA-010000 오류가 발생합니다.

커서 수 찾기 및 설정

이 번호는 일반적으로 설치 시 DBA에 의해 구성됩니다.현재 사용 중인 커서 수, 최대 수 및 구성은 Oracle SQL Developer의 관리자 기능에서 액세스할 수 있습니다.SQL에서 다음과 같이 설정할 수 있습니다.

ALTER SYSTEM SET OPEN_CURSORS=1337 SID='*' SCOPE=BOTH;

JVM의 JDBC와 DB의 커서 관련

다음 JDBC 오브젝트는 다음 데이터베이스 개념과 밀접하게 관련되어 있습니다.

  • JDBC Connection데이터베이스 세션의 클라이언트 표현으로 데이터베이스 트랜잭션을 제공합니다.연결은 한 번에 하나의 트랜잭션만 열 수 있습니다(단, 트랜잭션은 중첩될 수 있음).
  • JDBC ResultSet은 데이터베이스의 단일 커서로 지원됩니다.결과 집합에서 close()가 호출되면 커서가 해제됩니다.
  • JDBC CallableStatement는 데이터베이스에 저장 프로시저를 호출합니다.이 프로시저는 PL/SQL로 작성되는 경우가 많습니다.저장 프로시저는 0개 이상의 커서를 만들 수 있으며 커서를 JDBC ResultSet으로 반환할 수 있습니다.

JDBC는 스레드 세이프입니다.다양한 JDBC 오브젝트를 스레드 간에 전달해도 괜찮습니다.

예를 들어 한 스레드에 연결을 생성할 수 있습니다. 다른 스레드는 이 연결을 사용하여 PreparedStatement를 생성하고 세 번째 스레드는 결과 세트를 처리할 수 있습니다.하나의 주요 제약사항은 한 번에 하나의 Prepared Statement에서 여러 ResultSultSet을 열 수 없다는 것입니다.자세한 내용은 Oracle DB가 연결당 다중(병렬) 작업을 지원합니까?를 참조하십시오.

데이터베이스 커밋은 Connection에서 이루어지기 때문에 해당 Connection의 모든 DML(INSERT, UPDATE 및 DELETE)이 함께 커밋됩니다.따라서 동시에 여러 트랜잭션을 지원하려면 각 동시 트랜잭션에 대해 하나 이상의 연결이 있어야 합니다.

JDBC 개체를 닫는 중

ResultSet을 실행하는 일반적인 예는 다음과 같습니다.

Statement stmt = conn.createStatement();
try {
    ResultSet rs = stmt.executeQuery( "SELECT FULL_NAME FROM EMP" );
    try {
        while ( rs.next() ) {
            System.out.println( "Name: " + rs.getString("FULL_NAME") );
        }
    } finally {
        try { rs.close(); } catch (Exception ignore) { }
    }
} finally {
    try { stmt.close(); } catch (Exception ignore) { }
}

final 구는 close()에 의해 발생한 예외를 무시합니다.

  • {} catch {} 시도 없이 결과 집합을 닫기만 하면 작업이 실패하고 문이 닫히지 않을 수 있음
  • 발신자에게의 전파 시도 본문에 발생하는 예외를 허가합니다.스테이트먼트 작성 및 실행 등 루프오버가 있는 경우 루프 내의 각 스테이트먼트를 닫는 것을 잊지 마십시오.

Java 7에서는 Oracle이 AutoCloseable 인터페이스를 도입하여 Java 6의 대부분의 보일러 플레이트를 통사적인 설탕으로 대체하였습니다.

JDBC 객체 보유

JDBC 오브젝트는 로컬 변수, 오브젝트인스턴스 및 클래스 멤버로 안전하게 유지할 수 있습니다.일반적으로 다음 작업을 수행하는 것이 좋습니다.

  • 오브젝트 인스턴스 또는 클래스 멤버를 사용하여 Connections 및 Prepared Statements와 같이 장기간에 걸쳐 여러 번 재사용되는 JDBC 오브젝트를 보유합니다.
  • ResultSets는 일반적으로 단일 함수의 범위 내에서 취득, 루프오버 및 닫히므로 로컬 변수를 ResultSets에 사용합니다.

단, 한 가지 예외가 있습니다.EJB 또는 서블릿/J를 사용하는 경우SP 컨테이너는 엄격한 스레드화 모델을 따라야 합니다.

  • 애플리케이션 서버만 스레드 생성(수신 요청을 처리하는 데 사용)
  • (접속 풀에서 취득한) 접속을 작성하는 것은 어플리케이션서버뿐입니다.
  • 콜간의 값(상태)을 보존하는 경우는, 매우 주의할 필요가 있습니다.자신의 캐시나 정적 멤버에 값을 저장하지 마십시오.클러스터나 기타 이상한 조건에서는 안전하지 않습니다.어플리케이션서버가 데이터에 끔찍한 영향을 줄 수 있습니다.대신 스테이트풀빈 또는 데이터베이스를 사용합니다.
  • 특히 JDBC 오브젝트(Connections, ResultSets, PreparedStatements 등)를 다른 리모트 호출에 대해 보류하지 마십시오.이것에 대해서는, 애플리케이션 서버가 관리합니다.응용 프로그램서버는 접속 풀을 제공할 뿐만 아니라 Prepared Statements도 캐시합니다.

누수 방지

JDBC 누설을 검출하고 제거하기 위해 사용할 수 있는 프로세스와 툴은 다음과 같습니다.

  1. 개발 중에 버그를 조기에 잡는 것이 가장 좋은 방법입니다.

    1. 개발 프랙티스:개발의 베스트 프랙티스를 사용하면 소프트웨어가 개발자의 책상을 떠나기 전에 버그의 수를 줄일 수 있습니다.구체적인 프랙티스는 다음과 같습니다.

      1. 충분한 경험이 없는 사람들을 교육하기 위해 프로그래밍을 짝짓기
      2. 많은 눈이 하나보다 낫기 때문에 코드 리뷰
      3. 유닛 테스트. 테스트 툴에서 코드 베이스의 모든 것을 사용할 수 있기 때문에 리크 재현이 간단해집니다.
      4. 자체 라이브러리를 구축하지 않고 연결 풀링에 기존 라이브러리 사용
    2. 정적 코드 분석:정적 코드 분석을 수행하려면 우수한 Findbugs와 같은 도구를 사용합니다.close()가 올바르게 처리되지 않은 곳이 많이 있습니다.Findbugs는 Eclipse용 플러그인이 있지만 일회성용으로도 독립 실행되며 Jenkins CI 및 기타 빌드 도구와 통합됩니다.

  2. 실행 시:

    1. 유지성과 커밋

      1. ResultSet 홀드 기능이 ResultSet인 경우.CLOSE_CURRS_OVER_COMMIT를 지정하면 Connection.commit() 메서드가 호출되면 ResultSet이 닫힙니다.이것은 Connection.setHoldability() 또는 오버로드된 Connection.createStatement() 메서드를 사용하여 설정할 수 있습니다.
    2. 런타임에 로깅합니다.

      1. 코드에 좋은 로그 문을 넣습니다.고객, 지원 직원 및 팀원들이 교육을 받지 않고도 이해할 수 있도록 명확하고 이해하기 쉬워야 합니다.처리 로직을 추적할 수 있도록 간결하고 주요 변수 및 속성의 상태/내부 값 인쇄를 포함해야 합니다.양호한 로깅은 디버깅애플리케이션, 특히 이미 도입된 어플리케이션의 기본입니다.
      2. 디버깅 JDBC 드라이버를 프로젝트에 추가할 수 있습니다(디버깅을 위해 - 실제로 배포하지 않음).예를 들어 (사용하지 않았습니다) log4jdbc가 있습니다.그런 다음 이 파일에 대한 간단한 분석을 수행하여 어떤 실행이 해당 닫힘을 가지고 있지 않은지 확인해야 합니다.열림 및 닫힘 수를 계산하면 잠재적인 문제가 있는지 여부가 강조됩니다.

        1. 데이터베이스 모니터링SQL Developer 'Monitor SQL' 기능 또는 Quest의 TOAD와 같은 도구를 사용하여 실행 중인 응용 프로그램을 모니터링합니다.이 문서에서는 모니터링에 대해 설명합니다.모니터링하는 동안 열린 커서(예: v$sesstat 표)를 쿼리하고 해당 SQL을 검토합니다.커서의 수가 증가하고 있고 (가장 중요한 것은) 하나의 동일한 SQL 문에 의해 지배되는 경우 해당 SQL에서 누수가 발생했음을 알 수 있습니다.코드를 검색하여 검토합니다.

다른 생각

WeakReferences를 사용하여 닫히는 연결을 처리할 수 있습니까?

약한 참조와 소프트 참조는 JVM이 적합하다고 판단될 때 언제든지 참조를 가비지 수집하도록 개체를 참조할 수 있는 방법입니다(해당 개체에 대한 강력한 참조 체인이 없는 경우).

컨스트럭터에서 ReferenceQue를 소프트 또는 약한 Reference로 전달하면 오브젝트가 발생할 때(발생할 경우) 오브젝트가 GC 처리될 때 ReferenceQue에 배치됩니다.이 접근방식을 사용하면 오브젝트의 최종화와 상호 작용하여 그 시점에서 오브젝트를 닫거나 완료할 수 있습니다.

팬텀 참조는 좀 더 이상합니다.그 목적은 최종화를 제어하는 것뿐이지만 원래 오브젝트에 대한 참조를 얻을 수 없기 때문에 close() 메서드를 호출하는 것은 어렵습니다.

그러나 GC가 실행되는 시기를 제어하는 것은 좋은 방법이 거의 없습니다(Weak, Soft 및 PhantomReferences는 개체가 GC용으로 큐잉된 사실을 알려줍니다).실제로 JVM의 메모리 용량이 큰 경우(예: -Xmx2000m) 오브젝트를 GC하지 않고 ORA-01000이 계속 발생할 수 있습니다.JVM 메모리가 프로그램 요건에 비해 작을 경우 ResultSet 개체와 PreparedStatement 개체가 작성 직후(읽기 전)에 GC 처리되므로 프로그램이 실패할 수 있습니다.

TL;DR: 약한 참조 메커니즘은 Statement 및 ResultSet 개체를 관리하고 닫는 좋은 방법이 아닙니다.

나는 몇 가지 이해를 더하고 있다.

  1. objecct j 、 resultSet 。
  2. 하지만 Oracle 메모리를 확보하려면 결과 세트를 닫아야 합니다.대해
  3. 클로징 스테이트먼트
  4. SELECT / INSERT / UPDATE / DELETE 。
  5. SID를 할 수 . SID를 하여 각 할 수 . 마찬가지로 ORACLE DB는 연결 SID를 사용하여 각 연결을 식별할 수 있습니다.SID를 사용하다
  6. ORACLE의 jdbc(tcp)의 SID의 1입니다.
  7. 최대 커서를 500으로 설정하면 하나의 JDBC 세션/연결/SID에만 적용됩니다.
  8. 따라서 각각의 커서 수(문)를 사용하여 많은 JDBC 연결을 할 수 있습니다.
  9. JVM이 종료되면 모든 연결/커서가 닫히거나 해당 연결에 대한 JDBCC 연결이 닫힙니다.

sysdba로 로그인합니다.

Putty(Oracle 로그인):

  [oracle@db01 ~]$ sqlplus / as sysdba

SQLPlus의 경우:

: 용자 user user user :sys as sysdba

닫힌 커서가 없도록 session_cached_curs 값을 0으로 설정합니다.

 alter session set session_cached_cursors=0
 select * from V$PARAMETER where name='session_cached_cursors'

DB에서 연결별로 설정된 기존 OPEN_CURSORS 값 선택

 SELECT max(a.value) as highest_open_cur, p.value as max_open_cur FROM v$sesstat a, v$statname b, v$parameter p WHERE a.statistic# = b.statistic# AND b.name = 'opened cursors current' AND p.name= 'open_cursors'  GROUP BY p.value;

아래는 커서 값이 열려 있는 SID/연결 목록을 찾기 위한 쿼리입니다.

 SELECT a.value, s.username, s.sid, s.serial#
 FROM v$sesstat a, v$statname b, v$session s
 WHERE a.statistic# = b.statistic#  AND s.sid=a.sid 
 AND b.name = 'opened cursors current' AND username = 'SCHEMA_NAME_IN_CAPS'

아래 쿼리를 사용하여 열려 있는 커서의 SQL을 식별합니다.

 SELECT oc.sql_text, s.sid 
 FROM v$open_cursor oc, v$session s
 WHERE OC.sid = S.sid
 AND s.sid=1604
 AND OC.USER_NAME ='SCHEMA_NAME_IN_CAPS'

이제 코드를 디버깅하고 즐기세요!!!:)

다음과 같이 코드를 수정합니다.

try
{ //method try starts  
  String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
  pStmt = obj.getConnection().prepareStatement(sql);
  pStmt.setLong(1, subscriberID);
  for (String language : additionalLangs) {
    pStmt.setInt(2, Integer.parseInt(language));
    pStmt.execute();
  }
} //method/try ends
finally
{ //finally starts
   pStmt.close()
} 

정말 pStatement, 연결 및 결과를 종료하시겠습니까?

열려 있는 개체를 분석하려면 상태, 연결 및 결과 개체에 코드를 감싼 위임자 패턴을 삽입할 수 있습니다.그러면 어떤 물체가 정상적으로 닫히는지 알 수 있습니다.

예: pStmt = obj.getConnection().prepareStatement(sql);

    class obj{ 

    public Connection getConnection(){
    return new ConnectionDelegator(...here create your connection object and put it into ...);

    } 
}


class ConnectionDelegator implements Connection{
    Connection delegates;

    public ConnectionDelegator(Connection con){
       this.delegates = con;
    }

    public Statement prepareStatement(String sql){
        return delegates.prepareStatement(sql);
    }

    public void close(){
        try{
           delegates.close();
        }finally{
           log.debug(delegates.toString() + " was closed");
        }
    }
}

응용 프로그램이 응용 프로그램서버로서 Oracle WebLogic 상에서 실행되고 있는 Java EE 응용 프로그램인 경우, 이 문제의 원인으로 생각할 수 있는 것은 WebLogic 의 스테이트먼트 캐시 사이즈 설정입니다.

특정 데이터 원본의 스테이트먼트 캐시 크기 설정이 오라클 데이터베이스의 최대 열린 커서 수 설정과 거의 같거나 더 큰 경우 열려 있는 모든 커서가 WebLogic에 의해 열려 있는 캐시된 SQL 문에 의해 소비될 수 있으므로 ORA-01000 오류가 발생합니다.

이 문제를 해결하려면 Oracle 데이터베이스를 가리키는 각 WebLogic 데이터 소스의 [Statement Cache Size]설정을 데이터베이스의 최대 커서 수 설정보다 크게 낮춥니다.

WebLogic 10 Admin Console the 、 [ Services ](왼쪽 네비게이션) > [ Data Sources ]> [ Connection Pool ]탭에 각 데이터 소스의 스테이트먼트캐시 사이즈 설정이 표시됩니다.

나도 이 문제에 직면했었다.이전에는 다음과 같은 예외가 있었습니다.

java.sql.SQLException: - ORA-01000: maximum open cursors exceeded

스프링 프레임워크와 스프링 JDBC를 dao 레이어로 사용하고 있었습니다.

어플리케이션에서는 어떤 식으로든 커서가 누출되고 몇 분 정도 지나면 이 예외가 발생하곤 했습니다.

많은 디버깅과 분석을 통해 쿼리 실행 중 하나의 테이블에서 Indexing, Primary Key Unique Constraints에 문제가 있음을 알게 되었습니다.

응용 프로그램이 실수로 색인화된 을 업데이트하려고 했습니다.따라서 응용 프로그램이 인덱스된 열의 업데이트 쿼리를 누를 때마다 데이터베이스는 업데이트된 값을 기반으로 재인덱싱을 수행하려고 했습니다.커서가 새고 있었어요

쿼리 검색에 사용된 컬럼에 적절한 인덱싱을 수행하고 필요에 따라 적절한 제약을 적용하여 문제를 해결할 수 있었습니다.

오늘도 같은 문제(ORA-01000)에 직면했습니다.try{}에서는 (매번 파라미터를 변경할 때마다) Oracle DB에서 SELECT 문을 실행하기 위한 for 루프가 있었고, 마지막으로 {}에서는 평소와 같이 Resultset, Prepared Statement 및 Connection을 닫도록 코드를 설정했습니다.그러나 특정 루프 수(1000개)에 도달하자마자 열린 커서가 너무 많다는 Oracle 오류가 발생했습니다.

위의 Andrew Alcock의 투고를 바탕으로 데이터를 취득한 후 다시 루프하기 전에 각 결과 세트와 각 스테이트먼트를 닫도록 변경하였습니다.그것이 문제를 해결했습니다.

또한 동일한 문제가 다른 Oracle DB(ORA-01000)에 있는 Insert Statements의 다른 루프에서도 300개의 스테이트먼트를 실행한 후 발생했습니다.마찬가지로 동일한 방법으로 해결되었으므로 PreparedStatement 또는 ResultSet 또는 둘 다 닫힐 때까지 열린 커서로 간주됩니다.

autocommit=true로 설정했습니까?시도하지 않을 경우:

{ //method try starts  
    String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
    Connection conn = obj.getConnection()
    pStmt = conn.prepareStatement(sql);

    for (String language : additionalLangs) {
        pStmt.setLong(1, subscriberID);
        pStmt.setInt(2, Integer.parseInt(language));
        pStmt.execute();
        conn.commit();
    }
} //method/try ends { 
    //finally starts
    pStmt.close()
} //finally ends 

query를 클릭하여 열린 SQL을 찾습니다.

SELECT s.machine, oc.user_name, oc.sql_text, count(1) 
FROM v$open_cursor oc, v$session s
WHERE oc.sid = s.sid
and S.USERNAME='XXXX'
GROUP BY user_name, sql_text, machine
HAVING COUNT(1) > 2
ORDER BY count(1) DESC

이 문제는 주로 접속 풀링을 사용할 때 발생합니다.접속을 닫으면 접속 풀로 돌아가 해당 접속과 관련된 모든 커서가 닫히지 않기 때문입니다.데이터베이스에 대한 접속이 아직 열려 있기 때문입니다.따라서 풀 내 접속 아이돌 접속 시간을 줄이는 방법도 있습니다.따라서 접속이 10초 동안 아이돌 상태가 되면 데이터베이스 연결이 닫히고 풀에 넣기 위해 새로운 연결이 생성됩니다.

배치 처리를 사용하면 오버헤드가 줄어듭니다.예에 대해서는, 다음의 링크를 참조해 주세요.http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm

이 경우 Hibernate를 사용하여 동일한 Hibernate 맵엔티티를 참조하는 변수가 많았습니다.이러한 참조를 루프에 작성해 보존하고 있었습니다.각 참조는 커서를 열고 열린 상태로 유지했습니다.

우리는 코드를 실행하는 동안 열린 커서의 수를 체크하기 위한 쿼리를 사용하여 디버거를 실행하고 선택적으로 주석을 달아 이를 발견했습니다.

각 새로운 레퍼런스가 다른 커서를 여는 이유에 대해서는, 문제의 엔티티는 다른 엔티티의 컬렉션을 매핑하고 있었습니다.이것은 이것뿐만이 아니라, 페치 모드와 캐시의 설정 방법과 조합하고 있다고 생각합니다.휴지 상태 자체에서 열린 커서를 닫지 못하는 버그가 발생했지만 이후 버전에서 이러한 버그가 수정되었습니다.

어차피 같은 엔티티에 대해 중복된 참조를 그렇게 많이 가질 필요가 없었기 때문에, 그 모든 중복 참조의 작성과 보유를 중지하는 것이 해결책이었습니다.우리가 한번 그렇게 하면 떠나 있을 때 문제가 생긴다.

WildFly 및 Tomcat에서 Oracle 10g에 연결하는 데이터 소스에 문제가 있었습니다.

특정 조건에서는 statement.close()가 호출되어도 문이 닫히지 않았습니다.사용하고 있는 Oracle 드라이버 ojdbc7.jar에 문제가 있었습니다.이 드라이버는 Oracle 12c 및 11g용 드라이버로 Oracle 10g에서 사용할 때 문제가 있을 것 같아서 ojdbc5.jar로 다운그레이드하면 모든 것이 정상적으로 동작합니다.

1000회 이상 db를 조회하고 있었기 때문에 같은 문제에 직면했습니다.나는 try를 사용했고 마침내 내 코드로 입력했다.하지만 여전히 오류가 발생하고 있었다.

이 문제를 해결하기 위해 oracle db에 로그인하여 아래 쿼리를 실행했습니다.

ALTER SYSTEM SET open_set = 8000 Scope= BOTH;

그리고 이것은 나의 문제를 즉시 해결했다.

준비된 스테이트먼트 캐시 크기를 큰 값으로 설정한 후 이 문제가 발생하였습니다.준비된 문이 캐시에 저장되면 커서가 열린 상태로 유지됩니다.

언급URL : https://stackoverflow.com/questions/12192592/java-sql-sqlexception-ora-01000-maximum-open-cursors-exceeded

반응형