java.sql.SQLException :-ORA-01000 : 최대 열린 커서가 초과되었습니다
ORA-01000 SQL 예외가 발생합니다. 그래서 관련 질문이 있습니다.
- 최대 열린 커서는 JDBC 연결 수와 정확히 관련이 있습니까? 아니면 단일 연결에 대해 작성한 명령문 및 결과 세트 오브젝트와도 관련이 있습니까? (우리는 연결 풀을 사용하고 있습니다)
- 데이터베이스에서 연결과 같은 문 / 결과 개체 수를 구성하는 방법이 있습니까?
- 단일 스레드 환경에서 메소드 로컬 명령문 / 결과 오브젝트 대신 인스턴스 변수 명령문 / 결과 오브젝트를 사용하는 것이 바람직합니까?
-
루프에서 준비된 명령문을 실행하면이 문제가 발생합니까? (물론 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 -
단일 연결 개체에서 conn.createStatement () 및 conn.prepareStatement (sql)가 여러 번 호출되면 어떻게됩니까?
Edit1 : 6. Weak / Soft 참조 문 객체를 사용하면 누출을 방지하는 데 도움이됩니까?
Edit2 : 1. 어떤 방법이 있습니까, 내 프로젝트에서 누락 된 "statement.close ()"를 모두 찾을 수 있습니까? 메모리 누수가 아니라는 것을 알고 있습니다. 그러나 가비지 수집에 적합한 명령문 참조 (close ()가 수행되지 않은 곳)를 찾아야합니까? 사용 가능한 도구가 있습니까? 아니면 수동으로 분석해야합니까?
이해하도록 도와주세요.
해결책
Oracle DB에서 사용자 이름 -VELU에 대해 열린 커서를 찾으려면
ORALCE 시스템으로 이동하여 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을 열려고 시도하면 발생합니다.
일반적인 원인은 다음과 같습니다.
-
구성 실수
- 응용 프로그램에서 데이터베이스를 조회하는 응용 프로그램에 DB의 커서보다 많은 스레드가 있습니다. 데이터베이스의 커서 수보다 큰 연결 및 스레드 풀이있는 경우가 있습니다.
- 동일한 DB 인스턴스 (많은 스키마를 포함 할 것임)에 연결된 많은 개발자 또는 응용 프로그램이 있고 함께 너무 많은 연결을 사용하고 있습니다.
-
해결책:
- 데이터베이스 에서 커서 수 늘리기 (자원이 허용되는 경우) 또는
- 응용 프로그램의 스레드 수를 줄입니다.
-
커서 누출
- 애플리케이션이 ResultSets (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 연결 은 데이터베이스 세션 의 클라이언트 표현이며 데이터베이스 트랜잭션을 제공합니다 . 연결은 한 번에 하나의 트랜잭션 만 열 수 있지만 트랜잭션은 중첩 될 수 있습니다.
- JDBC ResultSet 은 데이터베이스 에서 단일 커서로 지원됩니다 . ResultSet에서 close ()가 호출되면 커서가 해제됩니다.
- JDBC CallableStatement 는 종종 PL / SQL로 작성된 데이터베이스에서 저장 프로 시저 를 호출합니다 . 스토어드 프로시 저는 0 개 이상의 커서를 작성하고 커서를 JDBC ResultSet으로 리턴 할 수 있습니다.
JDBC는 스레드로부터 안전합니다. 스레드간에 다양한 JDBC 객체를 전달하는 것이 좋습니다.
예를 들어, 하나의 스레드에서 연결을 작성할 수 있습니다. 다른 스레드는이 연결을 사용하여 PreparedStatement를 만들 수 있고 세 번째 스레드는 결과 집합을 처리 할 수 있습니다. 하나의 주요 제한 사항은 하나의 PreparedStatement에서 한 번에 둘 이상의 ResultSet을 열 수 없다는 것입니다. Oracle DB는 연결 당 여러 (병렬) 작업을 지원합니까?를 참조하십시오 .
데이터베이스 커밋은 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) { } }
finally 절이 close ()에 의해 발생 된 예외를 무시하는 방법에 유의하십시오.
- try {} catch {}없이 단순히 ResultSet을 닫으면 실패하여 명령문이 닫히지 않을 수 있습니다.
- 시도의 본문에서 발생한 예외가 호출자에게 전파되도록 허용하려고합니다. 예를 들어 문 생성 및 실행에 대해 루프가있는 경우 루프 내에서 각 문을 닫는 것을 잊지 마십시오.
Java 7에서 Oracle은 대부분의 Java 6 상용구를 멋진 구문 설탕으로 대체 하는 AutoCloseable 인터페이스 를 도입했습니다 .
JDBC 객체 보유
JDBC 객체는 로컬 변수, 객체 인스턴스 및 클래스 멤버에 안전하게 보관할 수 있습니다. 일반적으로 다음을 수행하는 것이 좋습니다.
- 오브젝트 인스턴스 또는 클래스 멤버를 사용하여 Connections 및 PreparedStatements와 같이 장기간 재사용되는 JDBC 오브젝트를 보유하십시오.
- ResultSets에 로컬 변수를 사용하십시오. 이는 일반적으로 단일 함수의 범위 내에서 확보되고 반복 된 다음 닫힙니다.
그러나 EJB 또는 Servlet / JSP 컨테이너를 사용하는 경우 엄격한 스레딩 모델을 따라야합니다.
- Application Server 만 스레드를 작성합니다 (수신 요청을 처리하는 데 사용됨).
- 응용 프로그램 서버 만 연결을 만듭니다 (연결 풀에서 가져옴).
- 호출간에 값 (상태)을 저장할 때 매우주의해야합니다. 자체 캐시 또는 정적 멤버에 값을 저장하지 마십시오. 이는 클러스터 및 기타 이상한 조건에서 안전하지 않으며 Application Server가 데이터에 끔찍한 작업을 수행 할 수 있습니다. 대신 Stateful Bean 또는 데이터베이스를 사용하십시오.
- 특히, 다른 원격 호출을 통해 JDBC 객체 (Connections, ResultSets, PreparedStatements 등)를 보유 하지 마십시오 . Application Server에서이를 관리하십시오. Application Server는 연결 풀을 제공 할뿐만 아니라 PreparedStatements도 캐시합니다.
누출 제거
JDBC 누출을 감지하고 제거하는 데 도움이되는 여러 프로세스와 도구가 있습니다.
-
개발하는 동안 버그를 조기에 발견하는 것이 가장 좋은 방법입니다.
-
개발 관행 : 좋은 개발 관행은 개발자의 책상을 떠나기 전에 소프트웨어의 버그 수를 줄여야합니다. 구체적인 사례는 다음과 같습니다.
-
정적 코드 분석 : 뛰어난 Findbugs 와 같은 도구 를 사용하여 정적 코드 분석을 수행합니다. 이것은 close ()가 올바르게 처리되지 않은 많은 장소를 선택합니다. Findbugs에는 Eclipse 용 플러그인이 있지만 일회성으로 독립형으로 실행되며 Jenkins CI 및 기타 빌드 도구에 통합되어 있습니다.
-
-
런타임시 :
-
유지성 및 커밋
- ResultSet 보유 가능성이 ResultSet.CLOSE_CURSORS_OVER_COMMIT이면 Connection.commit () 메소드가 호출 될 때 ResultSet이 닫힙니다. Connection.setHoldability () 또는 과부하 된 Connection.createStatement () 메소드를 사용하여 설정할 수 있습니다.
-
런타임시 로깅.
- 코드에 좋은 로그 문을 넣으십시오. 고객, 지원 직원 및 팀원이 교육없이 이해할 수 있도록 명확하고 이해할 수 있어야합니다. 그것들은 간결해야하며 처리 논리를 추적 할 수 있도록 주요 변수 및 속성의 상태 / 내부 값 인쇄를 포함해야합니다. 좋은 로깅은 특히 배포 된 애플리케이션 디버깅의 기본입니다.
-
디버깅 JDBC 드라이버를 프로젝트에 추가 할 수 있습니다 (디버깅을 위해 실제로 배포하지 마십시오). 한 가지 예 (사용하지 않은)는 log4jdbc 입니다. 그런 다음이 파일에 대해 간단한 분석을 수행하여 해당 실행이없는 실행을 확인하십시오. 잠재적 인 문제가있는 경우 열기 및 닫기 계산을 강조 표시해야합니다.
- 데이터베이스 모니터링 SQL Developer 'Monitor SQL'기능 또는 Quest 's TOAD 와 같은 도구를 사용하여 실행중인 애플리케이션을 모니터링하십시오 . 모니터링은 이 기사 에서 설명 합니다. 모니터링하는 동안 열린 커서 (예 : 테이블 v $ sesstat)를 쿼리하고 해당 SQL을 검토합니다. 커서 수가 증가하고 하나의 동일한 SQL 문이 지배하는 경우 (해당 중요하게) 해당 SQL에 누출이있는 것입니다. 코드를 검색하고 검토하십시오.
-
다른 생각들
WeakReferences를 사용하여 닫는 연결을 처리 할 수 있습니까?
약한 참조와 소프트 참조는 JVM이 참조가 적절하다고 판단 될 때 언제든지 해당 참조를 가비지 수집 할 수있는 방식으로 오브젝트를 참조 할 수있는 방법입니다 (해당 오브젝트에 대한 강력한 참조 체인이 없다고 가정).
생성자의 ReferenceQueue를 약하거나 약한 Reference에 전달하면 객체가 발생할 때 객체가 GC 될 때 객체가 ReferenceQueue에 배치됩니다. 이 방법을 사용하면 객체의 마무리와 상호 작용할 수 있으며 그 순간 객체를 닫거나 마무리 할 수 있습니다.
팬텀 레퍼런스는 조금 이상합니다. 그것들의 목적은 마무리를 제어하는 것이지만, 원래 객체에 대한 참조를 얻을 수 없으므로 close () 메소드를 호출하기가 어렵습니다.
그러나 GC가 실행될 때 제어하려고 시도하는 것은 좋은 생각이 아닙니다 (약함, 약함 및 팬텀 레퍼런스 는 객체가 GC를 위해 대기열에 있다는 사실 을 알려줍니다 ). 실제로 JVM의 메모리 양이 크면 (예 : -Xmx2000m) 객체를 GC 하지 않을 수 있으며 ORA-01000이 계속 발생합니다. JVM 메모리가 프로그램 요구 사항에 비해 작 으면, ResultSet 및 PreparedStatement 오브젝트가 작성 직후 (GSM에서 읽기 전에) GC되어 있음을 발견 할 수 있습니다. 이로 인해 프로그램이 실패 할 수 있습니다.
TL; DR : 약한 참조 메커니즘은 Statement 및 ResultSet 오브젝트를 관리하고 닫는 좋은 방법이 아닙니다.
나는 더 많은 이해를 추가하고 있습니다.
- 커서는 문장 목표에 관한 것입니다. resultSet도 연결 개체도 아닙니다.
- 그러나 여전히 오라클 메모리를 확보하려면 결과 집합을 닫아야합니다. 여전히 CURSORS에 포함되지 않은 결과 집합을 닫지 않으면
- Closing Statement 개체는 결과 집합 개체도 자동으로 닫습니다.
- 모든 SELECT / INSERT / UPDATE / DELETE 문에 대해 커서가 작성됩니다.
- Oracle SID를 사용하여 각 ORACLE DB 인스턴스를 식별 할 수 있습니다. 마찬가지로 ORACLE DB는 연결 SID를 사용하여 각 연결을 식별 할 수 있습니다. 두 SID가 다릅니다.
- ORACLE 세션은 jdbc (tcp) 연결에 지나지 않습니다. SID는 하나뿐입니다.
- 최대 커서를 500으로 설정하면 하나의 JDBC 세션 / 연결 / SID에만 해당됩니다.
- 따라서 우리는 각각의 커서 (상태)와 많은 JDBC 연결을 가질 수 있습니다.
- JVM이 종료되면 모든 연결 / 커서가 닫히거나 JDBCConnection이 닫힙니다. 해당 연결에 대한 CURSORS가 닫힙니다.
sysdba로 로그인하십시오.
퍼티 (Oracle 로그인)에서 :
[oracle@db01 ~]$ sqlplus / as sysdba
SqlPlus에서 :
사용자 이름: sys as sysdba
커서가 닫히지 않도록 session_cached_cursors 값을 0으로 설정하십시오.
alter session set session_cached_cursors=0 select * from V$PARAMETER where name='session_cached_cursors'
DB에서 연결 당 기존 OPEN_CURSORS valuse 세트 선택
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() }
pStatements, 연결 및 결과를 실제로 닫고 있습니까?
열린 객체를 분석하기 위해 위임자 패턴을 구현하여 상태, 연결 및 결과 객체 주위에 코드를 감쌀 수 있습니다. 개체가 성공적으로 닫히면 알 수 있습니다.
예 : 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 의 Statement Cache Size 설정입니다.
특정 데이터 소스에 대한 Statement Cache Size 설정이 Oracle 데이터베이스 최대 열린 커서 수 설정과 거의 같거나 크면 WebLogic에서 열린 상태로 유지되는 캐시 된 SQL 문에서 모든 열린 커서를 사용할 수 있습니다. ORA-01000 오류.
이 문제를 해결하려면 Oracle 데이터베이스를 가리키는 각 WebLogic 데이터 원본에 대한 Statement Cache Size 설정을 데이터베이스의 최대 커서 수 설정보다 크게 줄이십시오.
WebLogic 10 관리 콘솔에서 각 데이터 원본에 대한 문 캐시 크기 설정은 서비스 (왼쪽 탐색)> 데이터 원본> (개별 데이터 원본)> 연결 풀 탭에서 찾을 수 있습니다.
저도이 문제에 직면했습니다.
java.sql.SQLException: - ORA-01000: maximum open cursors exceeded
나는 dao 레이어를 위해 Spring JDBC 와 함께 Spring Framework 를 사용하고 있었다 .
내 응용 프로그램은 어떻게 든 커서를 누출하는 데 사용되었으며 몇 분 정도 지나면이 예외를 제공했습니다.
철저한 디버깅과 분석을 거친 결과, 실행중인 쿼리 에서 사용중인 테이블 중 하나에서 인덱싱, 기본 키 및 고유 제약 조건 에 문제가 있음을 발견했습니다 .
내 응용 프로그램 이 실수로 인덱싱 된 열 을 업데이트하려고했습니다 . 따라서 내 응용 프로그램이 인덱싱 된 열에서 업데이트 쿼리에 도달 할 때마다 데이터베이스는 업데이트 된 값을 기반으로 재 인덱싱을 시도했습니다. 커서 가 누출되었습니다 .
쿼리에서 검색하는 데 사용 된 열에 대해 적절한 인덱싱을 수행하고 필요할 때마다 적절한 제약 조건을 적용하여 문제를 해결할 수있었습니다.
오늘도 같은 문제 (ORA-01000)에 직면했습니다. try {}에 for 루프를 사용하여 Oracle DB에서 SELECT 문을 여러 번 실행하고 (매번 매개 변수를 변경할 때마다) finally {}에서는 Resultset, PreparedStatement 및 Connection을 평소와 같이 닫는 코드를 가졌습니다. . 그러나 특정 양의 루프 (1000)에 도달하자마자 너무 많은 열린 커서에 대한 Oracle 오류가 발생했습니다.
위의 Andrew Alcock의 게시물을 기반으로 루프 내부 에서 데이터를 가져온 후 다시 루프하기 전에 각 결과 집합과 각 문을 닫고 문제가 해결되도록 변경했습니다.
또한, 다른 Oracle DB (ORA-01000)의 다른 Insert 문 루프에서 똑같은 문제가 발생했습니다. 다시 동일한 방식으로 해결되었으므로 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
열린 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
1000 회 이상의 반복에 대해 db를 쿼리했기 때문에 동일한 문제에 직면했습니다. 내 코드에서 try와 마지막으로 사용했습니다. 그러나 여전히 오류가 발생했습니다.
이 문제를 해결하기 위해 방금 oracle db에 로그인하고 아래 쿼리를 실행했습니다.
ALTER SYSTEM SET open_cursors = 8000 SCOPE = BOTH;
그리고 이것은 내 문제를 즉시 해결했습니다.
일괄 처리를 사용하면 오버 헤드가 줄어 듭니다. 예는 다음 링크를 참조하십시오. http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm
우리의 경우 우리는 Hibernate를 사용하고 있었고 동일한 Hibernate 매핑 된 엔티티를 참조하는 많은 변수를 가지고있었습니다. 우리는 이러한 참조를 생성하고 루프에 저장했습니다. 각 참조는 커서를 열고 열어 두었습니다.
우리는 쿼리를 사용하여 코드를 실행하는 동안 열린 커서의 수를 확인하고 디버거를 사용하여 선택적으로 주석을 달아이를 발견했습니다.
각각의 새로운 참조가 다른 커서를 연 이유에 대해-문제의 엔터티에는 매핑 된 다른 엔터티의 컬렉션이 있었으며 이것이 관련이 있다고 생각합니다 (아마도 이것 만이 아니라 가져 오기 모드를 구성한 방법과 결합하여 캐시 설정). Hibernate 자체에는 열린 커서 를 닫는 데 실패하는 버그 가 있었지만 , 이후 버전에서 수정 된 것처럼 보입니다.
어쨌든 동일한 엔터티에 대한 중복 참조를 그렇게 많이 가질 필요가 없었기 때문에 해결책은 모든 중복 참조를 만들고 보유하는 것을 중지하는 것이 었습니다. 우리가 멀리 떨어져있을 때 문제를 해결했습니다.
이 문제는 주로 연결 풀링을 사용할 때 발생합니다. 연결을 닫으면 해당 연결이 연결 풀로 돌아가고 데이터베이스에 대한 연결이 아직 열려 있기 때문에 해당 연결과 관련된 모든 커서가 닫히지 않기 때문입니다. 따라서 한 가지 대안은 풀에서 연결의 유휴 연결 시간을 줄이는 것이므로 연결이 10 초 동안 유휴 상태가 될 때마다 데이터베이스에 대한 연결이 닫히고 풀에 넣을 새 연결이 생성 될 수 있습니다.
Oracle 10g에 연결하는 WildFly 및 Tomcat의 데이터 소스에이 문제가 발생했습니다.
특정 조건에서 statement.close ()가 호출되었을 때도 해당 문이 닫히지 않았 음을 발견했습니다. 문제는 우리가 사용하던 Oracle 드라이버 인 ojdbc7.jar에있었습니다. 이 드라이버는 Oracle 12c 및 11g 용이며 Oracle 10g와 함께 사용할 때 몇 가지 문제가있는 것 같습니다. 그래서 ojdbc5.jar로 다운 그레이드하고 이제 모든 것이 정상적으로 실행됩니다.
'Programming' 카테고리의 다른 글
iOS에서 ISO 8601 날짜를 얻으려면 어떻게합니까? (0) | 2020.08.06 |
---|---|
다음 기능을 표현합니다. 실제로 무엇을위한 것입니까? (0) | 2020.08.06 |
손가락, 안드로이드로 캔버스에 그리기 (0) | 2020.08.06 |
함수 제목의 화살표 연산자 (->) (0) | 2020.08.05 |
openssl verify를 사용하여 인증서 체인 확인 (0) | 2020.08.05 |