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

ORA-02055
2026년 08월 09일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-02055 distributed update operation failed; rollback required 는?

ORA-02055는 분산 데이터베이스 환경에서 원격 데이터베이스에 대한 업데이트 작업이 실패했을 때 발생하는 에러입니다. 이 에러는 단순한 실패 알림이 아니라, 현재 트랜잭션 전체가 롤백되어야 함을 명시적으로 요구하는 심각한 상태를 나타냅니다. 일반적으로 Database Link(DB Link)를 통해 원격 데이터베이스의 테이블을 수정하는 DML 작업 도중, 네트워크 장애나 원격 DB의 문제로 인해 두 Phase Commit이 실패하면서 이 에러가 트리거됩니다.

주요 발생 원인

  • 네트워크 단절 또는 원격 DB 연결 실패

분산 트랜잭션 도중 네트워크가 끊기거나 원격 DB 인스턴스가 다운된 경우 Oracle은 2PC(Two-Phase Commit) 프로토콜을 완료하지 못합니다. 이 상황에서 Oracle은 데이터 일관성을 위해 트랜잭션 전체를 롤백해야 한다고 판단하며 ORA-02055를 발생시킵니다.

  • In-doubt Transaction(미결 트랜잭션) 상태

분산 트랜잭션에서 PREPARE 단계는 성공했으나 COMMIT 단계에서 원격 노드와의 통신이 끊어지면, 해당 트랜잭션은 DBA_2PC_PENDING 뷰에 in-doubt 상태로 남게 됩니다. 이후 같은 세션에서 DML을 시도하면 Oracle이 미결 상태를 감지하고 ORA-02055를 반환하며 즉시 롤백을 강제합니다.

  • DB Link 권한 문제 또는 원격 테이블 잠금(Lock) 충돌

원격 데이터베이스에서 해당 테이블에 대한 Lock이 다른 세션에 의해 점유되어 있거나, DB Link 계정에 UPDATE 권한이 없는 경우에도 분산 업데이트가 실패합니다. 이 경우 Oracle은 분산 트랜잭션의 원자성을 보장할 수 없게 되어 롤백 요구와 함께 ORA-02055를 발생시킵니다.

해결 방법

원인 1: 네트워크/연결 문제 해결

먼저 DB Link 연결 상태를 확인하고 원격 DB 접근 가능 여부를 테스트합니다.

-- DB Link 목록 확인
SELECT db_link, username, host, created
FROM dba_db_links
ORDER BY created DESC;

-- DB Link 연결 테스트
SELECT * FROM dual@your_remote_dblink;

-- 현재 세션의 분산 트랜잭션 상태 확인
SELECT local_tran_id, global_tran_id, state, mixed, advice
FROM dba_2pc_pending;

연결이 복구된 후에는 반드시 ROLLBACK을 수행하고 트랜잭션을 재시도합니다.

-- 반드시 롤백 먼저 수행
ROLLBACK;

-- 이후 정상 트랜잭션 재시도
BEGIN
    UPDATE remote_table@your_remote_dblink
    SET column1 = 'new_value'
    WHERE id = 100;
    
    COMMIT;
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
END;
/

원인 2: In-doubt Transaction 강제 처리

DBA_2PC_PENDING에 미결 트랜잭션이 존재하는 경우 DBA가 수동으로 처리해야 합니다.

-- 미결 트랜잭션 상세 확인
SELECT local_tran_id,
       global_tran_id,
       state,
       mixed,
       advice,
       tran_comment,
       fail_time,
       force_time
FROM dba_2pc_pending;

-- 미결 트랜잭션 강제 COMMIT (원격 측도 커밋된 것이 확인된 경우)
EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id_value');

-- 또는 강제 롤백 (원격 측이 롤백된 것이 확인된 경우)
ROLLBACK FORCE 'local_tran_id_value';

-- 강제 커밋이 필요한 경우
COMMIT FORCE 'local_tran_id_value';

> ⚠️ COMMIT FORCE 또는 ROLLBACK FORCE는 반드시 원격 DB의 실제 상태를 확인한 후 사용해야 합니다. 잘못된 선택은 데이터 불일치를 초래합니다.

원인 3: 권한 및 Lock 문제 해결

-- 원격 DB에서 Lock 상태 확인 (원격 DB에 직접 접속 후)
SELECT s.sid,
       s.serial#,
       s.username,
       o.object_name,
       l.type,
       l.lmode,
       l.request
FROM v$lock l
JOIN v$session s ON l.sid = s.sid
JOIN dba_objects o ON l.id1 = o.object_id
WHERE s.username IS NOT NULL
ORDER BY s.sid;

-- Lock을 점유한 세션 강제 종료 (원격 DBA에게 요청 또는 직접 처리)
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;

-- DB Link 계정에 권한 부여 확인 (원격 DB에서 실행)
GRANT UPDATE ON schema_name.table_name TO dblink_user;

-- 권한 확인
SELECT grantee, table_name, privilege
FROM dba_tab_privs
WHERE grantee = 'DBLINK_USER';

예방 방법

  • 분산 트랜잭션 모니터링 자동화 및 Retry 로직 구현

운영 환경에서는 분산 트랜잭션 실패에 대비한 예외 처리와 자동 재시도 로직을 애플리케이션 또는 PL/SQL 레벨에서 반드시 구현해야 합니다. 아래와 같이 명시적인 ROLLBACK과 예외 처리를 항상 포함하면 ORA-02055 발생 시에도 안전하게 복구할 수 있습니다.

-- 권장되는 분산 트랜잭션 패턴
DECLARE
    v_retry_count NUMBER := 0;
    v_max_retry   NUMBER := 3;
BEGIN
    LOOP
        BEGIN
            UPDATE orders@remote_db
            SET status = 'PROCESSED'
            WHERE order_id = 12345;
            
            COMMIT;
            EXIT; -- 성공 시 루프 종료
        EXCEPTION
            WHEN OTHERS THEN
                ROLLBACK; -- ORA-02055 발생 시 반드시 롤백
                v_retry_count := v_retry_count + 1;
                IF v_retry_count >= v_max_retry THEN
                    RAISE; -- 최대 재시도 초과 시 에러 전파
                END IF;
                DBMS_LOCK.SLEEP(5); -- 5초 대기 후 재시도
        END;
    END LOOP;
END;
/
  • DBA_2PC_PENDING 정기 모니터링 및 알림 설정

In-doubt 트랜잭션이 오래 방치되면 리소스 고갈과 후속 트랜잭션 실패로 이어질 수 있습니다. 아래 쿼리를 스케줄러 잡으로 등록하여 미결 트랜잭션 발생 시 즉시 DBA에게 알림이 가도록 구성하는 것이 Best Practice입니다.

-- DBMS_SCHEDULER를 이용한 모니터링 잡 예시
BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        => 'CHECK_2PC_PENDING',
        job_type        => 'PLSQL_BLOCK',
        job_action      => '
            DECLARE
                v_count NUMBER;
            BEGIN
                SELECT COUNT(*) INTO v_count FROM dba_2pc_pending
                WHERE state = ''prepared''
                AND fail_time < SYSDATE - 1/24; -- 1시간 이상 미결
                
                IF v_count > 0 THEN
                    -- 알림 발송 로직 (이메일, 슬랙 등)
                    DBMS_OUTPUT.PUT_LINE(v_count || '' in-doubt transactions found!'');
                END IF;
            END;',
        start_date      => SYSTIMESTAMP,
        repeat_interval => 'FREQ=MINUTELY;INTERVAL=30',
        enabled         => TRUE,
        comments        => 'Monitor in-doubt distributed transactions'
    );
END;
/

관련 에러

  • ORA-02056: 분산 트랜잭션에서 2PC 프로토콜의 두 번째 단계(Commit phase) 실패와 관련된 에러로, ORA-02055와 함께 발생하는 경우가 많습니다.
  • ORA-01591: In-doubt 분산 트랜잭션이 잠금을 점유하고 있을 때 해당 리소스에 접근하려는 다른 트랜잭션에서 발생합니다.
  • ORA-02058: 원격 데이터베이스에서의 롤백이 실패했음을 나타내며, 분산 트랜잭션 롤백 체인에서 ORA-02055 이후 연달아 발생할 수 있습니다.
  • ORA-02054: 트랜잭션이 In-doubt 상태임을 나타내는 에러로, DBA_2PC_PENDING에 등록된 미결 트랜잭션에 직접 접근 시 발생합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기