[Oracle] “ORA-00257: archiver error” 발생원인 및 조치방법
오라클 개발용 DB를 사용 중 아래와 같이 “ORA-00257: archiver error”가 발생하여 DB 연결까지 안되는 사태가 발생했습니다. ORA-00257 오류는 오라클 데이터베이스의 아카이브 로그 디렉토리가 가득 차서 더 이상 로그 파일을 생성할 수 없을 때 발생합니다. 그래서 Archive Log가 뭐고, ORA-00257 오류를 해결하는 방법에 대해 정리하고자 합니다.
Caused by: org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: ORA-00257: archiver error. Connect internal only, until freed.
- 아카이브 로그(Archive Log)란?
- FRA(Fast Recovery Area) 공간확보 방법: 보존 정책 기반 삭제
- FRA 공간확보 방법: 상태 기반 메타데이터 삭제
1. 아카이브 로그(Archive Log)란?
아카이브 로그는 오라클 데이터베이스에서 발생하는 모든 데이터 변경 사항을 기록한 파일의 복사본입니다. 이는 데이터베이스 복구의 핵심 요소입니다. 아래와 같은 절차로 생성됩니다.

(출처: https://sapbasissolutions.wordpress.com/2018/11/26/how-oracle-database-redo-and-archived-logs-function/)
- 리두 로그 버퍼(Redo Log Buffer): 사용자가 INSERT, UPDATE, DELETE 등의 DML(데이터 조작어) 트랜잭션을 실행하면, 해당 변경 사항 정보(리두 엔트리)는 가장 먼저 SGA (System Global Area) 내의 메모리 영역에 있는 리두 로그 버퍼에 기록됩니다.
- 온라인 리두 로그(Online Redo Log) 파일: 백그라운드 프로세스인 LGWR(Log Writer)가 리두 로그 버퍼의 내용이 특정 조건(예: 1MB 이상의 변경, 3초 주기 등)을 만족할 때, 버퍼의 내용을 읽어 디스크의 온라인 리두 로그 파일에 순차적으로 기록합니다.
- 로그 스위치(Log Switch): 현재 사용 중인 리두 로그 그룹이 가득 차서 다음 그룹으로 전환될 때 (로그 스위치 발생), 오라클의 아카이버 프로세스(ARCH)가 가득 찬 리두 로그 그룹의 내용을 복사하여 별도의 디스크 공간에 저장합니다.
- 아카이브 로그 파일: 이렇게 복사되어 영구적으로 저장된 파일이 바로 아카이브 로그 파일 (Archive Redo Log File, ARC)입니다. 오래된 변경 기록(온라인 리두 로그)을 영구 보존하여, 미디어 장애(디스크 손상 등) 발생 시 데이터베이스를 복원하고 롤포워드(Roll-Forward) 복구를 수행할 때 사용됩니다.
FRA가 활성화되어 있으면 아카이브 로그 파일은 기본적으로 FRA 디렉토리에 저장됩니다. FRA 디렉토리가 물리적 또는 통계적으로 가득 차면 아카이브 로그는 더 이상 저장되지 않기 때문에 앞서 이야기한 것처럼 ORA-00257 오류가 발생합니다.
- FRA 디렉토리를 확인하는 방법
아카이브 로그 저장 경로: {DB_RECOVERY_FILE_DEST}/{DB_UNIQUE_NAME}/archivelog/{YYYY_MM_DD}/{파일명.arc}SQL> SHOW PARAMETER DB_RECOVERY_FILE_DEST; NAME TYPE VALUE ------------------------------------ ----------- ----------------------------------- db_recovery_file_dest string /u02/app/oracle/fast_recovery_area/ db_recovery_file_dest_size big integer 600G
- 물리적으로 가득 찬 경우는 리눅스 OS 관점에서 디스크 공간이 부족한 상태 ▶ 보존 정책 기반 삭제
#확인방법 : Use%가 100%인지 확인 $ df -h <FRA 경로의 마운팅 포인트>
- 통계적으로 가득 찬 경우는 오라클 DB 관점에서 설정된 FRA 용량 제한에 도달한 상태 ▶ 상태 기반 메타데이터 삭제
#확인방법 : USED_PCT가 100%인지 확인 SELECT NAME, ROUND(SPACE_LIMIT / 1024 / 1024) AS "TOTAL_MB", ROUND(SPACE_USED / 1024 / 1024) AS "USED_MB", ROUND(SPACE_RECLAIMABLE / 1024 / 1024) AS "RECLAIMABLE_MB", ROUND((SPACE_USED / SPACE_LIMIT) * 100) AS "USED_PCT" FROM V$RECOVERY_FILE_DEST;< 컬럼 설명 > NAME FRA 경로 (리눅스 경로) TOTAL_MB FRA에 할당된 총 크기 (DB_RECOVERY_FILE_DEST_SIZE 파라미터 값) USED_MB 현재 사용 중인 크기 RECLAIMABLE_MB RMAN 정책에 따라 삭제되어 재활용 가능한 공간 크기 (백업이 완료된 아카이브 로그 등) USED_PCT FRA 공간 사용률 (%)
2. FRA 공간확보 방법: 보존 정책 기반 삭제
아카이브 로그를 보존 정책(Retention Policy) 기반으로 삭제하는 절차는 RMAN의 DELETE OBSOLETE 명령을 활용하는 것입니다. 이 방법은 데이터베이스의 복구 가능성을 깨뜨리지 않고 가장 안전하게 공간을 확보하는 표준 절차입니다.
- rman 접속
$ rman target /
- 현재 보존 정책 확인
- 복구 기간 기반 (Recovery Window) : 특정 기간(예: 7일) 내의 어떤 시점으로든 복구할 수 있도록 보장합니다. 가장 일반적인 방식입니다.
- 중복 기반 (Redundancy) : 모든 데이터 파일 백업본을 지정된 횟수만큼 보존합니다.
RMAN> SHOW RETENTION POLICY; (복구 기간 기반) RMAN retention policy is set to recovery window of 7 days (중복 기반) RMAN retention policy is set to redundancy 1
- 삭제 대상 확인(선택 사항)
실제로 어떤 백업 및 아카이브 로그 파일이 삭제 대상인지 확인할 수 있습니다. 출력 목록에 있는 파일들은 현재 설정된 보존 정책을 만족시키고 남는 ‘잉여 파일’이므로 삭제해도 안전합니다.RMAN> REPORT OBSOLETE;
- 보존 정책에 따른 삭제 실행
REPORT OBSOLETE;에 나왔던 모든 파일을 삭제하며, 아카이브 로그 역시 복구 기간 유지에 필요하지 않다면 함께 삭제됩니다.RMAN> DELETE OBSOLETE;
- 아카이브 로그 복사본 정리(선택 사항)
만약 아카이브 로그를 복사본 형태로 관리하고 있다면, 다음 명령을 통해 OBSOLETE 처리된 아카이브 로그의 복사본도 함께 정리할 수 있습니다.RMAN> DELETE OBSOLETE ARCHIVELOG ALL;
- 백업이 성공적으로 완료된 아카이브 로그 파일 삭제(선택 사항)
DELETE OBSOLETE;는 이미 백업된 로그가 아닌, 복구 정책상 필요 없는 로그만 삭제합니다. 만약 아카이브 로그가 너무 빨리 쌓여 보존 정책에 따라도 아직 삭제 시점이 되지 않았다면, 추가 공간 확보를 위해 아래 명령을 실행합니다.#모든 아카이브 로그를 읽어 백업 세트(Backup Set)로 생성한 후, 원본 아카이브 로그 파일들을 삭제합니다. RMAN> BACKUP ARCHIVELOG ALL DELETE INPUT; #압축된 백업 세트로 생성한 후, 원본 아카이브 로그 파일들을 삭제합니다. #BACKUPSET 저장 경로: {DB_RECOVERY_FILE_DEST}/{DB_UNIQUE_NAME}/backupset/{YYYY_MM_DD}/{백업파일.bkp} RMAN> BACKUP AS COMPRESSED BACKUPSET ARCHIVELOG ALL DELETE INPUT; #압축된 백업 세트를 생성하여 FRA가 아닌, 지정된 디렉토리에 저장합니다. RMAN> BACKUP FORMAT <디렉토리 경로> AS COMPRESSED BACKUPSET ARCHIVELOG ALL DELETE INPUT; DELETE OBSOLETE;실행 스크립트 등록(선택 사항)
oracle 사용자로 아래 쉘 스크립트 파일을 crontab에 등록하여 주기적으로 실행합니다.$ vi cleanup_obsolete.sh #!/bin/bash rman target / << EOF DELETE NOPROMPT OBSOLETE; EXIT; EOF find "{DB_RECOVERY_FILE_DEST}/{DB_UNIQUE_NAME}/archivelog/" -type d -empty -delete- FRA 크기 확장(장기적인 해결책)
#FRA 크기를 1000GB로 확장 SQL> ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 1000G SCOPE=BOTH;
3. FRA 공간확보 방법: 상태 기반 메타데이터 삭제
리눅스 rm를 사용하여 아카이브 로그나 백업 파일을 디스크에서 직접 삭제했거나, 백업 파일이 저장된 디스크나 테이프 장치에 물리적인 오류가 발생하여 RMAN이 해당 파일에 접근할 수 없게 되었을 때 메타데이터를 삭제해야 합니다.
- RMAN 카탈로그(메타데이터) 동기화
CROSSCHECK 명령어는 RMAN 메타데이터에 등록된 백업 파일이나 아카이브 로그가 실제 디스크에 존재하는지 확인합니다.- 만약 파일이 존재하면 상태는 AVAILABLE로 유지됩니다.
- 만약 파일이 디스크에서 사라졌다면 (OS 명령어로 수동 삭제했거나, 디스크 오류 등으로 접근 불가능할 경우) 상태를 EXPIRED로 변경합니다.
RMAN> CROSSCHECK BACKUP; RMAN> CROSSCHECK ARCHIVELOG ALL;
- 만료된 파일 삭제
1단계에서 EXPIRED로 상태가 변경된 파일 정보를 RMAN 카탈로그에서 깨끗하게 제거하여 불일치 문제를 해결합니다.RMAN> DELETE EXPIRED BACKUP; RMAN> DELETE EXPIRED ARCHIVELOG ALL;
CROSSCHECK 명령을 실행하지 않고 DELETE 명령을 실행하면 아래와 같은 오류가 발생합니다. RMAN의 메타데이터(카탈로그) 정보와 실제 디스크에 저장된 아카이브 로그 파일의 상태가 일치하지 않아 삭제하지 못한 파일이 있다는 경고입니다. RMAN-06207: WARNING: 165 objects could not be deleted for DISK channel(s) due RMAN-06208: to mismatched status. Use CROSSCHECK command to fix status RMAN-06210: List of Mismatched objects - 실제 아카이브 파일 삭제 및 공간 확보
위 두 단계를 완료하여 RMAN 카탈로그가 정리되었다면, 아카이브 로그 보관 정책에 따라 일정 기간이 경과한 로그 파일을 삭제합니다.# 예: 7일 이전 로그 삭제 RMAN> DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE - 7';
- 백업 및 원본 삭제(가장 강력한 공간 확보 방법, 선택 사항)
3단계로도 여전히 실패하고 로그가 삭제되지 않는다면, 해당 로그 파일이 특정 백업 세트에 필수적인 종속성을 가지고 있거나 손상되었을 가능성이 있습니다. 이 경우, 아카이브 로그 백업 후 원본을 즉시 삭제하는 DELETE INPUT 전략을 사용해 보세요.RUN { ALLOCATE CHANNEL disk1 DEVICE TYPE DISK; BACKUP ARCHIVELOG ALL DELETE INPUT; RELEASE CHANNEL disk1; } - 보존 정책 기반 삭제와 상태 기반 삭제를 모두 수행하는 자동화 쉘 스크립트(crontab 등록 방법)
#!/bin/bash # ========================================================== # RMAN 포괄적 정리 스크립트: 메타데이터 정리 및 정책 기반 삭제 # ---------------------------------------------------------- # 오라클 환경 변수 설정 (필수: 실제 환경에 맞게 수정) export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1 export ORACLE_SID=ORCLDB export PATH=$ORACLE_HOME/bin:$PATH # FRA 경로 설정 (필수: 실제 환경에 맞게 수정) FRA_DIR="/u02/app/oracle/fast_recovery_area" # 로그 파일 경로 설정 (필수: 실제 환경에 맞게 수정) LOG_DIR="/u01/app/oracle/scripts/log" LOG_FILE="$LOG_DIR/rman_full_cleanup_$(date +%Y%m%d%H%M%S).log" DATE_INFO=$(date '+%Y-%m-%d %H:%M:%S') # 로그 디렉토리가 없으면 생성 (오라클 유저 소유로) if [ ! -d "$LOG_DIR" ]; then mkdir -p "$LOG_DIR" fi # 로그 시작 기록 echo "==========================================================" >> "$LOG_FILE" echo "RMAN Full Cleanup Start: $DATE_INFO" >> "$LOG_FILE" echo "==========================================================" >> "$LOG_FILE" # RMAN 명령어 실행 블록 # ------------------------------------------------------------------------------------------------ # 1. 메타데이터 정리 (상태 기반 삭제) # 2. 정책 기반 삭제 # ------------------------------------------------------------------------------------------------ rman target / log="$LOG_FILE" append << EOF # 섹션 1: 상태 기반 메타데이터 정리 (불일치 해소) # 1-1. 백업 세트 및 복사본, 아카이브 로그, 컨트롤파일 복사본 크로스 체크 (파일 존재 여부 확인) CROSSCHECK BACKUP; CROSSCHECK ARCHIVELOG ALL; CROSSCHECK COPY OF CONTROLFILE; # 1-2. EXPIRED로 표시된 백업 및 아카이브 로그 메타데이터 삭제 DELETE NOPROMPT EXPIRED BACKUP; DELETE NOPROMPT EXPIRED ARCHIVELOG ALL; DELETE NOPROMPT EXPIRED COPY OF CONTROLFILE; # 섹션 2: 보존 정책 기반 삭제 # 2-1. 삭제 대상 보고 REPORT OBSOLETE; # 2-2. 보존 정책을 초과한 모든 백업 및 아카이브 로그 삭제 DELETE NOPROMPT OBSOLETE; # 2-3. 필요 시 지정한 기간(15일) 이전에 완료된 복사본을 강제로 삭제 #DELETE NOPROMPT BACKUP COMPLETED BEFORE 'SYSDATE - 15'; #DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE - 15'; #DELETE NOPROMPT COPY OF CONTROLFILE COMPLETED BEFORE 'SYSDATE - 15'; EXIT; EOF # RMAN 종료 시간 기록 echo "==========================================================" >> "$LOG_FILE" echo "RMAN Full Cleanup Finished: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE" echo "==========================================================" >> "$LOG_FILE" # 7일이 지난 오래된 스크립트 로그 파일 삭제 find "$LOG_DIR" -type f -name 'rman_full_cleanup_*.log' -mtime +7 -exec rm {} \; # FRA 디렉토리의 빈 하위 디렉토리 삭제 find "$FRA_DIR/archivelog/" -type d -empty -delete -print
