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

ORA-00476
2026년 06월 13일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-00476 RECO process terminated with error 는?

ORA-00476 에러는 Oracle 데이터베이스의 백그라운드 프로세스 중 하나인 RECO(Recoverer) 프로세스가 비정상적으로 종료되었을 때 발생하는 에러입니다. RECO 프로세스는 분산 트랜잭션(Distributed Transaction)에서 네트워크 장애나 원격 데이터베이스 장애로 인해 미완료 상태로 남겨진 In-Doubt 트랜잭션을 자동으로 복구하는 역할을 담당합니다. 이 에러가 발생하면 분산 트랜잭션의 자동 복구가 중단되며, In-Doubt 트랜잭션이 지속적으로 쌓여 데이터 정합성 문제 및 잠금(Lock) 이슈로 이어질 수 있어 즉각적인 조치가 필요합니다.


주요 발생 원인

1. 네트워크 장애 또는 원격 데이터베이스 연결 실패

RECO 프로세스가 In-Doubt 트랜잭션을 해소하기 위해 원격 데이터베이스에 접속을 시도할 때, 네트워크 불안정이나 원격 DB 다운 상태가 지속되면 RECO 프로세스 내부에서 반복적인 오류가 발생합니다. 특히 Oracle Net(SQLNet) 설정의 타임아웃 파라미터가 잘못 구성된 경우, 연결 대기 중에 내부 오류가 누적되어 결국 RECO 프로세스가 강제 종료되는 상황으로 이어집니다.

2. In-Doubt 트랜잭션의 과도한 누적 및 데이터 딕셔너리 손상

분산 트랜잭션 환경에서 네트워크 단절이 빈번하게 발생하면 DBA_2PC_PENDING 뷰에 In-Doubt 트랜잭션이 대량으로 누적됩니다. 이 상태에서 RECO 프로세스가 손상된 데이터 딕셔너리 항목이나 내부 UNDO 세그먼트 관련 오브젝트에 접근할 때 내부 예외(Internal Exception)가 발생하여 프로세스가 비정상 종료될 수 있습니다.

3. Oracle 내부 버그 또는 메모리/리소스 부족

특정 Oracle 버전에서는 RECO 프로세스와 관련된 내부 버그로 인해 예기치 않은 ORA-00476이 발생할 수 있습니다. 또한 SGA(System Global Area) 또는 PGA(Program Global Area) 메모리가 부족하거나, OS 수준의 리소스(파일 디스크립터, 프로세스 수 등)가 한계에 도달한 경우에도 RECO 프로세스가 정상적으로 동작하지 못하고 종료될 수 있습니다.


해결 방법

원인 1 해결: 네트워크 및 원격 DB 연결 점검

우선 alert log와 trace 파일을 확인하여 어느 원격 DB 링크(DB Link)에서 문제가 발생하는지 파악합니다.

-- 현재 In-Doubt 트랜잭션 확인
SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID, STATE, MIXED, ADVICE,
       TRAN_COMMENT, FAIL_TIME, FORCE_TIME, RETRY_TIME
FROM   DBA_2PC_PENDING
ORDER  BY FAIL_TIME;

-- DB Link 상태 확인
SELECT DB_LINK, USERNAME, HOST, CREATED
FROM   DBA_DB_LINKS;

-- 특정 DB Link 연결 테스트
SELECT 1 FROM DUAL@원격_DB_LINK_NAME;

sqlnet.ora 파일에서 타임아웃 설정을 조정하여 RECO 프로세스의 무한 대기를 방지합니다.

-- sqlnet.ora 설정 예시 (OS 레벨 편집)
-- SQLNET.EXPIRE_TIME = 10
-- TCP.CONNECT_TIMEOUT = 15
-- SQLNET.OUTBOUND_CONNECT_TIMEOUT = 15

-- 변경 후 리스너 재시작 여부 확인
-- lsnrctl reload (OS 커맨드)

-- 적용된 파라미터 확인
SHOW PARAMETER DISTRIBUTED_TRANSACTIONS;

원인 2 해결: In-Doubt 트랜잭션 수동 처리

자동 복구가 불가능한 In-Doubt 트랜잭션은 DBA가 직접 COMMIT 또는 ROLLBACK을 수행하여 제거해야 합니다. 반드시 원격 데이터베이스 관리자와 협의한 후 처리해야 데이터 정합성을 보장할 수 있습니다.

-- In-Doubt 트랜잭션 상세 조회
SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID, STATE, ADVICE
FROM   DBA_2PC_PENDING;

-- ADVICE가 'COMMIT'인 경우 강제 커밋
COMMIT FORCE '로컬_트랜잭션_ID';
-- 예시:
-- COMMIT FORCE '22.31.1';

-- ADVICE가 'ROLLBACK'인 경우 강제 롤백
ROLLBACK FORCE '로컬_트랜잭션_ID';
-- 예시:
-- ROLLBACK FORCE '22.31.1';

-- 처리 후 DBA_2PC_PENDING 확인
SELECT COUNT(*) AS PENDING_COUNT FROM DBA_2PC_PENDING;

-- 처리된 내역 확인 (DBA_2PC_NEIGHBORS)
SELECT LOCAL_TRAN_ID, IN_OUT, DATABASE, DBUSER_OWNER, INTERFACE
FROM   DBA_2PC_NEIGHBORS
WHERE  LOCAL_TRAN_ID = '22.31.1';

원인 3 해결: 메모리 및 패치 적용

메모리 관련 파라미터를 점검하고 필요 시 조정합니다.

-- 현재 SGA 및 PGA 설정 확인
SHOW PARAMETER SGA_TARGET;
SHOW PARAMETER PGA_AGGREGATE_TARGET;
SHOW PARAMETER MEMORY_TARGET;

-- RECO 관련 파라미터 확인
SHOW PARAMETER OPEN_LINKS;
SHOW PARAMETER DISTRIBUTED_LOCK_TIMEOUT;

-- DISTRIBUTED_TRANSACTIONS 파라미터가 0이면 RECO 비활성화됨 (주의)
-- 분산 트랜잭션 사용 시 반드시 0보다 크게 설정
ALTER SYSTEM SET DISTRIBUTED_TRANSACTIONS = 32 SCOPE=SPFILE;

-- 변경 후 인스턴스 재시작 필요
-- SHUTDOWN IMMEDIATE;
-- STARTUP;

-- alert log에서 ORA-00476 발생 시점의 에러 스택 확인 쿼리
-- (alert log 경로 확인)
SELECT VALUE FROM V$DIAG_INFO WHERE NAME = 'Diag Trace';

-- 현재 백그라운드 프로세스 상태 확인
SELECT PNAME, PID, SPID, BACKGROUND, LATCHWAIT, LATCHSPIN
FROM   V$PROCESS
WHERE  PNAME IS NOT NULL
ORDER  BY PNAME;

Oracle Support(MOS)에서 해당 버전의 RECO 관련 버그 패치를 확인하고, 최신 PSU(Patch Set Update) 또는 RU(Release Update) 적용을 검토합니다.


예방 방법

1. 분산 트랜잭션 모니터링 자동화 및 주기적 정리

In-Doubt 트랜잭션이 일정 시간 이상 남아있을 경우 DBA에게 알림을 발송하는 모니터링 스크립트를 운영 환경에 등록하여 주기적으로 상태를 점검해야 합니다. 아래 스크립트를 Cron Job 또는 Oracle Scheduler에 등록하여 자동화할 수 있습니다.

-- Oracle Scheduler를 이용한 모니터링 Job 생성 예시
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    JOB_NAME        => 'MONITOR_2PC_PENDING',
    JOB_TYPE        => 'PLSQL_BLOCK',
    JOB_ACTION      => '
      DECLARE
        V_COUNT NUMBER;
      BEGIN
        SELECT COUNT(*) INTO V_COUNT FROM DBA_2PC_PENDING
        WHERE  FAIL_TIME < SYSDATE - 1/24; -- 1시간 이상 된 트랜잭션
        IF V_COUNT > 0 THEN
          -- 실제 환경에서는 UTL_MAIL 등을 이용해 알림 발송
          DBMS_OUTPUT.PUT_LINE(''WARNING: '' || V_COUNT || '' In-Doubt transactions detected!'');
        END IF;
      END;',
    START_DATE      => SYSTIMESTAMP,
    REPEAT_INTERVAL => 'FREQ=MINUTELY;INTERVAL=30',
    ENABLED         => TRUE,
    COMMENTS        => 'Monitor In-Doubt transactions every 30 minutes'
  );
END;
/

-- Job 상태 확인
SELECT JOB_NAME, STATE, LAST_RUN_DURATION, NEXT_RUN_DATE
FROM   DBA_SCHEDULER_JOBS
WHERE  JOB_NAME = 'MONITOR_2PC_PENDING';

2. sqlnet.ora 및 분산 트랜잭션 파라미터 최적화

네트워크 타임아웃 파라미터를 적절히 설정하면 RECO 프로세스가 불필요하게 오랫동안 응답 없는 원격 연결을 기다리는 것을 방지할 수 있습니다. DISTRIBUTED_LOCK_TIMEOUT 파라미터와 OPEN_LINKS 파라미터도 환경에 맞게 튜닝하여 RECO 프로세스의 안정성을 높여야 합니다.

-- 권장 파라미터 설정 예시
ALTER SYSTEM SET DISTRIBUTED_LOCK_TIMEOUT = 60 SCOPE=BOTH;
ALTER SYSTEM SET OPEN_LINKS = 4 SCOPE=SPFILE;
-- (OPEN_LINKS 변경은 재시작 필요)

-- 설정 확인
SELECT NAME, VALUE, DESCRIPTION
FROM   V$PARAMETER
WHERE  NAME IN ('distributed_lock_timeout','open_links',
                'distributed_transactions','open_links_per_instance');

관련 에러

  • ORA-01591: 분산 트랜잭션이 In-Doubt 상태로 남아 있어 잠금이 해제되지 않을 때 발생하는 에러로, ORA-00476과 함께 나타나는 경우가 많습니다.
  • ORA-02050: 분산 트랜잭션이 롤백되었으나 일부 원격 노드에서 완전히 처리되지 않았을 때 발생합니다.
  • ORA-02054: In-Doubt 상태의 트랜잭션 ID를 나타내며, DBA_2PC_PENDING에 기록되는 관련 에러입니다.
  • ORA-00481: LMON(Lock Monitor) 프로세스가 종료되었을 때 발생하는 유사한 백그라운드 프로세스 종료 에러입니다.
  • ORA-07445 / ORA-00600: RECO 프로세스가 내부 버그에 의해 강제 종료될 때 alert log에 ORA-00476과 함께 기록되는 내부 에러 코드입니다. 이 경우 Oracle Support에 SR(Service Request)을 오픈하여 해당 trace 파일을 제출해야 합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기