Oracle ORA-04092 오류 원인과 해결 방법 완벽 가이드

ORA-04092
2026년 08월 26일 | DBMS Error 가이드

이 글에서 다루는 내용

ORA-04092 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

ORA-04092 cannot COMMIT in a trigger 는?

ORA-04092는 Oracle 데이터베이스에서 트리거(Trigger) 내부에 COMMIT 또는 ROLLBACK과 같은 트랜잭션 제어 명령어(TCL)를 사용했을 때 발생하는 에러입니다. Oracle은 트리거가 호출된 DML 문장과 동일한 트랜잭션 컨텍스트 안에서 실행되기 때문에, 트리거 내에서 독립적으로 COMMIT을 수행하는 것을 허용하지 않습니다. 이 에러는 특히 레거시 시스템을 유지보수하거나 비즈니스 로직을 트리거에 과도하게 집어넣은 설계에서 자주 나타납니다.


주요 발생 원인

1. 트리거 본문에 직접 COMMIT/ROLLBACK 사용

가장 흔한 원인으로, 개발자가 트리거 내부에서 변경사항을 즉시 확정하려는 의도로 COMMIT을 직접 작성하는 경우입니다. Oracle 트리거는 DML 이벤트와 동일한 트랜잭션에 묶여 있기 때문에, 트리거 안에서 COMMIT을 호출하면 부모 트랜잭션 전체에 영향을 미칠 수 있어 Oracle 엔진이 이를 차단합니다. 결과적으로 ORA-04092가 발생하며 트리거 실행 자체가 실패합니다.

2. 트리거에서 COMMIT을 포함한 저장 프로시저(Stored Procedure) 호출

트리거 본문에서 직접 COMMIT을 쓰지 않더라도, 내부적으로 COMMIT을 수행하는 저장 프로시저나 패키지 프로시저를 호출할 경우에도 동일한 에러가 발생합니다. 이 경우 에러 메시지만으로는 원인 파악이 어렵기 때문에 Call Stack을 추적해야 합니다. 특히 공통 모듈로 만들어진 로깅(Logging) 프로시저가 내부적으로 COMMIT을 수행하는 구조일 때 이런 문제가 빈번하게 발생합니다.

3. PRAGMA AUTONOMOUS_TRANSACTION 없이 독립 트랜잭션 처리 시도

일부 개발자들은 트리거 내에서 감사(Audit) 로그나 이력 테이블에 데이터를 기록하고 즉시 COMMIT하고 싶어합니다. 이때 PRAGMA AUTONOMOUS_TRANSACTION 선언 없이 COMMIT을 시도하면 ORA-04092가 발생합니다. 자율 트랜잭션(Autonomous Transaction)을 올바르게 선언하지 않으면 트리거의 트랜잭션 경계를 벗어나는 것이 불가능하기 때문입니다.


해결 방법

원인 1 해결: 트리거에서 COMMIT 제거

트리거 내부의 COMMIT을 제거하고, 트랜잭션 제어는 트리거를 호출한 애플리케이션 또는 상위 PL/SQL 블록에서 처리하도록 구조를 변경합니다.

-- 잘못된 예시 (ORA-04092 발생)
CREATE OR REPLACE TRIGGER trg_emp_audit
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
    INSERT INTO emp_audit_log (emp_id, action, action_date)
    VALUES (:NEW.employee_id, 'INSERT', SYSDATE);

    COMMIT; -- ❌ 트리거 내 COMMIT 금지!
END;
/

-- 올바른 예시 (COMMIT 제거)
CREATE OR REPLACE TRIGGER trg_emp_audit
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
    INSERT INTO emp_audit_log (emp_id, action, action_date)
    VALUES (:NEW.employee_id, 'INSERT', SYSDATE);
    -- COMMIT은 애플리케이션 레이어에서 처리
END;
/

원인 2 해결: 호출 프로시저에서 COMMIT 분리

COMMIT을 포함한 프로시저를 트리거에서 호출하는 경우, 해당 프로시저에서 COMMIT을 제거하거나 AUTONOMOUS_TRANSACTION으로 전환해야 합니다.

-- 문제가 되는 로깅 프로시저 (COMMIT 포함)
CREATE OR REPLACE PROCEDURE log_action(p_msg IN VARCHAR2) IS
BEGIN
    INSERT INTO system_log (log_msg, log_date)
    VALUES (p_msg, SYSDATE);
    COMMIT; -- ❌ 이 프로시저를 트리거에서 호출하면 ORA-04092 발생
END;
/

-- 수정된 로깅 프로시저 (AUTONOMOUS_TRANSACTION 적용)
CREATE OR REPLACE PROCEDURE log_action(p_msg IN VARCHAR2) IS
    PRAGMA AUTONOMOUS_TRANSACTION; -- ✅ 자율 트랜잭션 선언
BEGIN
    INSERT INTO system_log (log_msg, log_date)
    VALUES (p_msg, SYSDATE);
    COMMIT; -- 자율 트랜잭션 범위 내에서만 COMMIT
END;
/

원인 3 해결: PRAGMA AUTONOMOUS_TRANSACTION 올바르게 적용

트리거 내에서 반드시 독립적인 COMMIT이 필요한 감사 로그나 에러 로그 기록의 경우, 트리거 자체 또는 호출 서브프로그램에 PRAGMA AUTONOMOUS_TRANSACTION을 선언합니다.

-- PRAGMA AUTONOMOUS_TRANSACTION을 사용한 감사 트리거
CREATE OR REPLACE TRIGGER trg_salary_audit
AFTER UPDATE OF salary ON employees
FOR EACH ROW
DECLARE
    PRAGMA AUTONOMOUS_TRANSACTION; -- ✅ 자율 트랜잭션 선언
BEGIN
    INSERT INTO salary_audit_log (
        emp_id,
        old_salary,
        new_salary,
        changed_by,
        changed_date
    ) VALUES (
        :OLD.employee_id,
        :OLD.salary,
        :NEW.salary,
        USER,
        SYSDATE
    );
    COMMIT; -- 자율 트랜잭션 내에서 안전하게 COMMIT
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK; -- 자율 트랜잭션 내 롤백 (부모 트랜잭션에 영향 없음)
        RAISE;
END;
/

> ⚠️ 주의: PRAGMA AUTONOMOUS_TRANSACTION을 사용할 경우, 자율 트랜잭션 내의 변경사항은 부모 트랜잭션이 ROLLBACK되어도 취소되지 않습니다. 따라서 감사 로그, 에러 로그 등 항상 기록이 남아야 하는 용도에만 제한적으로 사용해야 합니다.


예방 방법

1. 트리거 설계 원칙 수립 및 코드 리뷰 강화

트리거 내부에는 TCL(COMMIT, ROLLBACK, SAVEPOINT) 명령어를 절대 작성하지 않는다는 팀 내 코딩 표준을 명문화하십시오. 코드 리뷰 체크리스트에 “트리거 내 TCL 사용 여부”를 필수 항목으로 포함시키고, 가능하다면 PL/SQL 정적 분석 도구(예: SonarQube for PL/SQL, Toad Code Analysis)를 활용하여 자동으로 탐지하는 체계를 마련하는 것이 좋습니다.

2. 공통 프로시저의 AUTONOMOUS_TRANSACTION 여부를 문서화

공통으로 사용하는 로깅 프로시저, 에러 핸들링 프로시저 등에 PRAGMA AUTONOMOUS_TRANSACTION이 선언되어 있는지 여부를 API 문서 또는 주석으로 명확히 기록해 두십시오. 트리거에서 호출 가능한 프로시저와 그렇지 않은 프로시저를 구분하여 관리하면, 새로운 트리거를 작성할 때 실수를 크게 줄일 수 있습니다.


관련 에러

  • ORA-04091: table is mutating, trigger/function may not see it — 트리거가 자신을 발생시킨 테이블을 읽거나 수정하려 할 때 발생하며, ORA-04092와 함께 트리거 설계 오류의 대표적인 사례입니다.
  • ORA-04093: references to columns of type LONG are not allowed in triggers — 트리거 내에서 LONG 타입 컬럼을 참조할 때 발생합니다.
  • ORA-06519: active autonomous transaction detected and rolled back — AUTONOMOUS_TRANSACTION 블록 내에서 COMMIT이나 ROLLBACK 없이 종료될 때 발생하며, 자율 트랜잭션 사용 시 반드시 주의해야 합니다.
  • ORA-00060: deadlock detected while waiting for resource — 잘못 설계된 트리거가 잠금 경쟁을 일으킬 때 연쇄적으로 발생할 수 있습니다.

DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기