2026년 07월 01일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-01042 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-01042 detaching a session with open cursors not allowed 는?
ORA-01042 에러는 Oracle 데이터베이스 세션이 열린 커서(Open Cursor)를 보유한 상태에서 세션 분리(Detach)를 시도할 때 발생하는 오류입니다. 주로 Oracle의 XA(분산 트랜잭션) 환경이나 멀티스레드 애플리케이션에서 커서를 명시적으로 닫지 않은 채 세션을 끊으려 할 때 나타납니다. 이 에러는 데이터베이스 리소스 누수와 직결되며, 방치할 경우 ORA-01000(maximum open cursors exceeded) 같은 2차 에러로 이어질 수 있습니다.
주요 발생 원인
- XA 트랜잭션 환경에서 커서 미닫힘
Oracle XA(eXtended Architecture) 분산 트랜잭션 환경에서는 세션을 분리하기 전에 모든 커서가 반드시 닫혀 있어야 합니다. Java EE / Jakarta EE 기반의 WAS(WebLogic, JBoss, WebSphere 등)에서 Connection Pool을 통해 XA 커넥션을 사용할 때, 트랜잭션 종료 전 커서를 명시적으로 닫지 않으면 이 에러가 발생합니다. 특히 예외 처리 블록에서 커서 닫기를 누락하는 경우가 많습니다.
- 애플리케이션 코드의 잘못된 커서 관리
JDBC, OCI, Pro*C 등 다양한 Oracle 인터페이스에서 PreparedStatement, ResultSet, CallableStatement 등을 finally 블록 또는 try-with-resources 구문 없이 사용하면 커서가 열린 상태로 남게 됩니다. 비즈니스 로직에서 예외가 발생했을 때 커서를 닫는 코드가 실행되지 않아 세션 분리 시점에 ORA-01042가 트리거됩니다. 이 경우 애플리케이션 전체 코드 레벨의 리뷰가 필요합니다.
- 커넥션 풀 반환 시 정리 미흡
커넥션 풀(DBCP, HikariCP, UCP 등)에서 커넥션을 반환할 때 내부적으로 세션 분리(detach) 작업이 이루어집니다. 이때 해당 커넥션에 열린 커서가 존재하면 Oracle 드라이버가 ORA-01042를 반환합니다. 특히 오래된 버전의 JDBC 드라이버나 커넥션 풀 설정이 잘못된 경우, testOnReturn 또는 resetOnReturn 옵션이 누락되어 커서 정리가 이루어지지 않는 상황이 발생합니다.
해결 방법
1. 커서 강제 조회 및 수동 종료
현재 세션 또는 특정 세션에서 열린 커서 현황을 확인하고 세션을 종료합니다.
-- 현재 열린 커서 수 확인
SELECT
s.sid,
s.serial#,
s.username,
s.program,
COUNT(c.cursor#) AS open_cursors
FROM
v$session s
JOIN
v$open_cursor c ON s.saddr = c.saddr
WHERE
s.status = 'ACTIVE'
GROUP BY
s.sid, s.serial#, s.username, s.program
ORDER BY
open_cursors DESC;
-- 특정 세션에서 열린 커서 상세 확인
SELECT
c.cursor#,
c.sql_text,
c.last_sql_active_time
FROM
v$open_cursor c
JOIN
v$session s ON c.saddr = s.saddr
WHERE
s.sid = :target_sid
ORDER BY
c.last_sql_active_time DESC;
-- 문제 세션 강제 종료 (DBA 권한 필요)
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
2. XA 트랜잭션 환경에서의 커서 정리
XA 트랜잭션 사용 시 xa_end() 호출 전 모든 커서를 닫아야 합니다. JDBC 기반 예제는 아래와 같습니다.
-- PL/SQL 예제: 커서를 명시적으로 닫고 트랜잭션 종료
DECLARE
CURSOR emp_cur IS
SELECT employee_id, first_name, salary
FROM employees
WHERE department_id = 10;
v_emp emp_cur%ROWTYPE;
BEGIN
OPEN emp_cur;
LOOP
FETCH emp_cur INTO v_emp;
EXIT WHEN emp_cur%NOTFOUND;
-- 비즈니스 로직 처리
DBMS_OUTPUT.PUT_LINE('EMP: ' || v_emp.first_name);
END LOOP;
-- 반드시 커서를 닫은 후 커밋 또는 세션 작업 수행
CLOSE emp_cur;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
-- 예외 발생 시에도 커서 닫기
IF emp_cur%ISOPEN THEN
CLOSE emp_cur;
END IF;
ROLLBACK;
RAISE;
END;
/
3. OPEN_CURSORS 파라미터 및 누수 모니터링
-- 현재 OPEN_CURSORS 파라미터 확인
SHOW PARAMETER open_cursors;
-- 인스턴스 레벨 커서 통계 확인
SELECT
name,
value
FROM
v$sysstat
WHERE
name IN (
'opened cursors cumulative',
'opened cursors current',
'session cursor cache hits'
);
-- 커서를 가장 많이 열고 있는 SQL 추출
SELECT
oc.sql_text,
oc.user_name,
COUNT(*) AS cursor_count
FROM
v$open_cursor oc
GROUP BY
oc.sql_text, oc.user_name
HAVING
COUNT(*) > 10
ORDER BY
cursor_count DESC;
-- OPEN_CURSORS 파라미터 동적 변경 (임시 조치)
ALTER SYSTEM SET open_cursors = 500 SCOPE = BOTH;
4. 커넥션 반환 전 커서 정리 확인 쿼리
-- 비정상적으로 많은 커서를 보유한 세션 탐지
SELECT
s.sid,
s.serial#,
s.username,
s.osuser,
s.machine,
s.program,
s.status,
COUNT(oc.cursor#) AS open_cursor_count
FROM
v$session s
LEFT JOIN
v$open_cursor oc ON s.saddr = oc.saddr
GROUP BY
s.sid, s.serial#, s.username, s.osuser,
s.machine, s.program, s.status
HAVING
COUNT(oc.cursor#) > 50
ORDER BY
open_cursor_count DESC;
예방 방법
- 애플리케이션 레벨에서 반드시
try-with-resources패턴 적용
Java 기반 애플리케이션에서는 Connection, PreparedStatement, ResultSet 등 모든 JDBC 리소스를 try-with-resources 구문으로 감싸야 합니다. 이 패턴은 정상 종료는 물론 예외 발생 시에도 자동으로 close()를 호출하여 커서 누수를 원천 차단합니다. PL/SQL의 경우에는 EXCEPTION 절에 반드시 %ISOPEN 체크 후 CLOSE 구문을 포함하는 코딩 표준을 수립해야 합니다. 또한 코드 리뷰 단계에서 커서 관리 누락 여부를 체크리스트 항목으로 포함시키는 것이 중요합니다.
- 정기적인 커서 모니터링 및 Alert 설정
AWR(Automatic Workload Repository) 또는 OEM(Oracle Enterprise Manager)을 활용하여 세션별 열린 커서 수를 주기적으로 모니터링하는 Job을 설정합니다. 특정 세션이 OPEN_CURSORS 파라미터의 80% 이상을 사용하면 알림을 발송하는 모니터링 정책을 수립하고, DBMS_SCHEDULER를 이용해 커서 누수 감지 쿼리를 일 1회 이상 실행하여 로그를 남기도록 구성합니다. 이를 통해 장애가 발생하기 전 선제적으로 문제를 탐지하고 대응할 수 있습니다.
관련 에러
- ORA-01000:
maximum open cursors exceeded—OPEN_CURSORS파라미터 한도 초과 시 발생하며, ORA-01042와 함께 커서 관리 부실의 대표적인 증상입니다. - ORA-01001:
invalid cursor— 이미 닫혔거나 유효하지 않은 커서를 조작하려 할 때 발생합니다. - ORA-02089:
COMMIT is not allowed in a subordinate session— XA 분산 트랜잭션 환경에서 부적절한 COMMIT 시도 시 발생하며, ORA-01042와 유사한 XA 관련 에러입니다. - ORA-24323:
value not allowed— OCI 환경에서 세션 관리 오류 시 함께 나타날 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.