2026년 06월 13일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-00604 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-00604 error occurred at recursive SQL level 는?
ORA-00604는 Oracle 데이터베이스가 내부적으로 실행하는 재귀적 SQL(Recursive SQL) 처리 도중 오류가 발생했을 때 나타나는 에러입니다. 재귀적 SQL이란 사용자가 직접 실행하는 SQL이 아닌, Oracle 엔진이 데이터 딕셔너리 조회, 트리거 실행, 공간 관리 등을 위해 내부적으로 자동 실행하는 SQL을 의미합니다. 일반적으로 이 에러 단독으로 발생하기보다는 ORA-00942, ORA-01031, ORA-04098 등 다른 에러와 함께 스택 형태로 출력되며, 근본 원인은 함께 출력된 하위 에러 메시지에서 찾아야 합니다.
주요 발생 원인
1. 로그온/로그오프 트리거의 오류
가장 흔한 원인 중 하나로, 데이터베이스에 AFTER LOGON ON DATABASE 또는 BEFORE LOGOFF ON DATABASE 트리거가 설정되어 있을 때 해당 트리거 내부의 코드에 문제가 있으면 발생합니다. 예를 들어, 트리거가 참조하는 테이블이 삭제되었거나 권한이 변경된 경우, 또는 트리거 자체의 PL/SQL 로직에 버그가 있는 경우 모든 사용자의 로그인 시도마다 ORA-00604가 반복적으로 발생합니다. 이 경우 DBA 권한으로 접속하여 트리거를 즉시 비활성화하거나 수정해야 합니다.
2. 데이터 딕셔너리 손상 또는 권한 문제
Oracle이 내부 작업을 수행하기 위해 SYS 스키마의 데이터 딕셔너리 뷰나 테이블에 접근할 때 해당 객체가 손상되었거나 필요한 권한이 누락된 경우 발생할 수 있습니다. 특히 부주의한 패치 적용, 불완전한 업그레이드, 또는 SYS 객체를 직접 수정한 경우에 이 문제가 발생합니다. 데이터 딕셔너리의 무결성이 훼손된 경우에는 DBMS_METADATA 패키지 재컴파일 또는 utlrp.sql 스크립트 실행이 필요할 수 있습니다.
3. 잘못된 스키마 수준 트리거 또는 DDL 트리거
CREATE, DROP, ALTER 등의 DDL 이벤트에 반응하는 DDL 트리거나 특정 스키마에 종속된 트리거가 잘못 작성된 경우에도 ORA-00604가 발생합니다. 예를 들어 DDL 트리거 내에서 존재하지 않는 테이블에 감사 로그를 INSERT하려 할 때, 해당 테이블이 없으면 재귀 SQL 레벨에서 오류가 발생합니다. 이런 경우에는 해당 트리거를 찾아 비활성화한 후 원인을 분석해야 합니다.
해결 방법
원인 1 해결: 로그온 트리거 비활성화 및 수정
먼저 현재 존재하는 로그온/로그오프 트리거를 조회합니다.
-- 데이터베이스 레벨 트리거 조회
SELECT TRIGGER_NAME, TRIGGER_TYPE, TRIGGERING_EVENT, STATUS
FROM DBA_TRIGGERS
WHERE TRIGGERING_EVENT LIKE '%LOGON%'
OR TRIGGERING_EVENT LIKE '%LOGOFF%';
문제가 되는 트리거를 비활성화합니다.
-- 트리거 비활성화 (SYSDBA 권한 필요)
ALTER TRIGGER SYS.LOGON_AUDIT_TRIGGER DISABLE;
-- 또는 특정 스키마의 모든 트리거 비활성화
ALTER TRIGGER HR.MY_LOGON_TRIGGER DISABLE;
트리거 내용을 확인하고 오류를 수정합니다.
-- 트리거 소스 코드 확인
SELECT TEXT
FROM DBA_SOURCE
WHERE NAME = 'LOGON_AUDIT_TRIGGER'
AND TYPE = 'TRIGGER'
ORDER BY LINE;
-- 트리거가 참조하는 테이블 존재 여부 확인
SELECT TABLE_NAME FROM DBA_TABLES WHERE TABLE_NAME = 'AUDIT_LOG';
-- 수정 후 트리거 재활성화
ALTER TRIGGER SYS.LOGON_AUDIT_TRIGGER ENABLE;
원인 2 해결: 무효화된 객체 재컴파일
-- 무효화된 객체 목록 조회
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM DBA_OBJECTS
WHERE STATUS = 'INVALID'
ORDER BY OWNER, OBJECT_TYPE, OBJECT_NAME;
-- 특정 스키마의 무효 객체 일괄 재컴파일
EXEC DBMS_UTILITY.COMPILE_SCHEMA(SCHEMA => 'HR', COMPILE_ALL => FALSE);
-- 전체 데이터베이스 무효 객체 재컴파일 (sqlplus에서 실행)
-- @$ORACLE_HOME/rdbms/admin/utlrp.sql
원인 3 해결: DDL 트리거 비활성화 및 원인 테이블 생성
-- DDL 트리거 목록 조회
SELECT TRIGGER_NAME, TRIGGERING_EVENT, STATUS, OWNER
FROM DBA_TRIGGERS
WHERE TRIGGERING_EVENT LIKE '%DDL%'
OR TRIGGERING_EVENT LIKE '%CREATE%'
OR TRIGGERING_EVENT LIKE '%DROP%';
-- 문제 DDL 트리거 비활성화
ALTER TRIGGER AUDIT_SCHEMA.DDL_AUDIT_TRG DISABLE;
-- 누락된 감사 테이블 생성
CREATE TABLE AUDIT_SCHEMA.DDL_AUDIT_LOG (
LOG_ID NUMBER GENERATED ALWAYS AS IDENTITY,
EVENT_DATE DATE DEFAULT SYSDATE,
DB_USER VARCHAR2(100),
EVENT_TYPE VARCHAR2(50),
OBJECT_TYPE VARCHAR2(50),
OBJECT_NAME VARCHAR2(128),
CONSTRAINT PK_DDL_AUDIT PRIMARY KEY (LOG_ID)
);
-- 트리거 재활성화
ALTER TRIGGER AUDIT_SCHEMA.DDL_AUDIT_TRG ENABLE;
에러 스택에서 근본 원인 파악하기
-- alert log에서 에러 스택 확인 (뷰를 통한 조회)
SELECT ORIGINATING_TIMESTAMP, MESSAGE_TEXT
FROM V$DIAG_ALERT_EXT
WHERE MESSAGE_TEXT LIKE '%ORA-00604%'
OR MESSAGE_TEXT LIKE '%recursive SQL%'
ORDER BY ORIGINATING_TIMESTAMP DESC
FETCH FIRST 20 ROWS ONLY;
-- 현재 세션의 에러 정보 확인
SELECT * FROM V$SESSION
WHERE STATUS = 'ACTIVE'
AND USERNAME IS NOT NULL;
예방 방법
1. 트리거 생성 전 철저한 테스트 및 예외 처리 적용
로그온 트리거나 DDL 트리거는 데이터베이스 전체에 영향을 미치기 때문에 반드시 개발/테스트 환경에서 충분히 검증한 후 운영 환경에 적용해야 합니다. 특히 트리거 내부에는 반드시 EXCEPTION 블록을 포함하여 내부 오류가 발생하더라도 데이터베이스 접속 자체가 차단되지 않도록 방어 코드를 작성하는 것이 Best Practice입니다.
-- 안전한 로그온 트리거 작성 예시
CREATE OR REPLACE TRIGGER SAFE_LOGON_TRIGGER
AFTER LOGON ON DATABASE
BEGIN
-- 실제 비즈니스 로직
INSERT INTO AUDIT_SCHEMA.LOGIN_LOG(USER_NAME, LOGIN_TIME)
VALUES (SYS_CONTEXT('USERENV','SESSION_USER'), SYSDATE);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
-- 에러 발생 시 로그인을 막지 않고 조용히 무시
NULL;
END;
/
2. 정기적인 데이터베이스 헬스 체크 및 무효 객체 모니터링
운영 환경에서는 주기적으로 무효화된 객체와 비활성 트리거를 점검하는 모니터링 쿼리를 스케줄링하고, Oracle DBMS_SCHEDULER를 활용하여 자동으로 재컴파일을 시도하는 유지보수 Job을 설정해 두는 것이 좋습니다. 패치 적용이나 업그레이드 후에는 반드시 utlrp.sql을 실행하여 무효 객체를 정리하는 절차를 표준 운영 프로세스로 수립해야 합니다.
관련 에러
- ORA-00942:
table or view does not exist— 트리거가 참조하는 테이블이 없을 때 ORA-00604와 함께 자주 발생합니다. - ORA-01031:
insufficient privileges— 트리거 실행 계정에 권한이 없을 때 재귀 SQL 레벨에서 함께 출력됩니다. - ORA-04098:
trigger is invalid and failed re-validation— 트리거 자체가 무효 상태일 때 ORA-00604와 쌍으로 발생하는 대표적인 에러입니다. - ORA-00600:
internal error code— 데이터 딕셔너리 수준의 심각한 내부 오류 시 ORA-00604와 함께 나타날 수 있으며, Oracle Support 케이스 오픈이 필요합니다. - ORA-04031:
unable to allocate memory— SGA 메모리 부족으로 내부 재귀 SQL 실행에 실패할 경우 동반 출력될 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.