DBA 실무/Oracle(오라클)

ORA-00600 [3005]로 DB가 안 열릴 때 — 컨트롤파일 재생성 복구 기록

isony 2026. 8. 14. 08:32
반응형

ORA-00600 [3005]로 DB가 안 열릴 때 — 컨트롤파일 재생성 복구 기록

Oracle 10.2.0.3 (32-bit Windows) / NOARCHIVELOG 환경에서 ALTER DATABASE OPEN이 ORA-00600: internal error code, arguments: [3005], [1], [345], [3], [0], [0], [], [] 로 실패하던 DB를 컨트롤파일 재생성으로 살린 기록입니다. 중간에 판단을 한 번 잘못했고, 그 부분도 그대로 남겼습니다.

 

1. 상황

  • Oracle Database 10g Enterprise Edition 10.2.0.3.0 — 32-bit Windows
  • NOARCHIVELOG 모드
  • 데이터파일 21개, 온라인 redo 3그룹(각 500MB)
  • 마지막 백업 없음

STARTUP 하면 MOUNT까지는 올라가는데 OPEN에서 죽습니다.

데이터베이스가 마운트되었습니다.
ORA-00600: 내부 오류 코드, 인수 : [3005], [1], [345], [3], [0], [0], [], []

2. ORA-00600은 인자가 전부다

ORA-00600은 "커널 내부에서 뭔가 잘못됐다"는 것 외에 아무 의미가 없습니다. 첫 번째 인자가 사실상 진짜 에러 코드이고, 나머지는 컨텍스트입니다.

alert log 위치:

SHOW PARAMETER background_dump_dest;   -- 또는 diagnostic_dest

$ORACLE_BASE/admin/<SID>/bdump/alert_<SID>.log

인자 해석

인자 값 의미

1번 3005 오류 식별자 (redo 계열)
2번 1 thread 1
3번 345 시퀀스 345
4번 3 그룹 3

당시 v$log는 이랬습니다.

GROUP#  SEQUENCE#  BYTES       STATUS     FIRST_TIME
     1        343  524288000   INACTIVE   26/07/25
     3        342  524288000   INACTIVE   26/07/16
     2        344  524288000   CURRENT    26/08/03

CURRENT가 344, 라운드로빈상 다음 차례는 그룹 3(342를 담고 있던 가장 오래된 그룹) → 시퀀스 345. 인자 [345], [3]과 정확히 일치합니다.

즉, OPEN 과정에서 redo thread를 열며 그룹 3에 시퀀스 345를 할당하는 순간 실패하고 있었습니다.

3. 먼저 복구가 필요한 상태인지 확인

SELECT log_mode, open_mode, checkpoint_change# FROM v$database;
SELECT * FROM v$recover_file;
SELECT status, COUNT(*), MIN(checkpoint_change#), MAX(checkpoint_change#)
  FROM v$datafile_header GROUP BY status;
SELECT MIN(checkpoint_change#), MAX(checkpoint_change#) FROM v$datafile;

결과:

LOG_MODE      OPEN_MODE   CHECKPOINT_CHANGE#
NOARCHIVELOG  MOUNTED     3.4146E10

v$recover_file → 선택된 레코드가 없습니다.

STATUS   COUNT(*)  MIN(CKPT)   MAX(CKPT)
ONLINE         21  3.4146E10   3.4146E10

v$recover_file이 비어 있고 21개 파일의 checkpoint SCN이 전부 같습니다. 여기서 "일관 상태니 복구 불필요"라고 판단했는데, 이게 나중에 틀린 것으로 드러납니다. (→ 6절)

한 가지 팁: 3.4146E10 같은 지수 표기는 수십만 단위 차이를 가려버립니다.

SET NUMWIDTH 20
SELECT MIN(checkpoint_change#), MAX(checkpoint_change#),
       COUNT(DISTINCT checkpoint_change#)
  FROM v$datafile_header;

4. 1차 시도 — 로그 클리어 (실패)

그룹 3의 물리 파일 문제일 수 있으니 비워봅니다.

SELECT group#, status, type, member FROM v$logfile ORDER BY group#;

세 그룹 모두 STATUS 공백(정상), 경로는 C:\ORACLE10G\ORADATA\REDO0[1-3].LOG.

ALTER DATABASE CLEAR LOGFILE GROUP 3;
-- 데이타베이스가 변경되었습니다.

ALTER DATABASE OPEN;
-- ORA-00600: ... [3005], [1], [345], [3], [0], [0], [], []

로그를 비웠는데 인자가 완전히 동일합니다.

→ 물리 redo 파일이 아니라 컨트롤파일 안의 redo thread 레코드가 깨진 것. 그룹 3의 내용을 지워도 컨트롤파일이 여전히 "345를 그룹 3에"라는 잘못된 상태를 고집하고 있습니다.

5. 2차 시도 — 컨트롤파일 재생성

5-1. 정보 확보 (MOUNT 상태에서)

SET LINESIZE 200 PAGESIZE 500
SELECT file#, name FROM v$datafile ORDER BY file#;
SELECT name FROM v$tempfile;     -- ★ 반드시 기록
SELECT name FROM v$controlfile;

v$tempfile은 꼭 적어두세요. 컨트롤파일을 재생성하면 tempfile 정보가 사라져서 나중에 수동으로 다시 추가해야 합니다.

5-2. trace 스크립트 뽑기

udump 폴더를 뒤질 필요 없이 경로를 직접 지정할 수 있습니다.

ALTER DATABASE BACKUP CONTROLFILE TO TRACE AS 'C:\oracle10g\cf_raw.sql';

5-3. 콜드 백업

SHUTDOWN IMMEDIATE

데이터파일이 여러 드라이브에 흩어져 있으면 전부 복사해야 합니다. 이 사례는 C:\ORACLE10G\ORADATA\에 3개, D:\ORADATA\에 18개였습니다.

여기까지가 되돌릴 수 있는 마지막 지점입니다.

5-4. 스크립트 편집

cf_raw.sql 안에는 두 벌이 들어 있습니다.

-- Set #1. NORESETLOGS case     ← 온라인 로그가 살아있을 때
-- Set #2. RESETLOGS case       ← 온라인 로그가 손상됐을 때

이번엔 Set #2를 썼습니다. 그리고 CREATE CONTROLFILE ~ ; 한 덩어리만 남기고 STARTUP NOMOUNT, RECOVER DATABASE, ALTER DATABASE OPEN RESETLOGS, ALTER TABLESPACE TEMP ADD TEMPFILE 줄은 전부 제거합니다. 이 명령들은 결과를 보면서 직접 칠 겁니다.

CREATE CONTROLFILE REUSE DATABASE "ORCL" RESETLOGS  NOARCHIVELOG
    MAXLOGFILES 16
    MAXLOGMEMBERS 3
    MAXDATAFILES 100
    MAXINSTANCES 8
    MAXLOGHISTORY 292
LOGFILE
  GROUP 1 'C:\ORACLE10G\ORADATA\REDO01.LOG'  SIZE 500M,
  GROUP 2 'C:\ORACLE10G\ORADATA\REDO02.LOG'  SIZE 500M,
  GROUP 3 'C:\ORACLE10G\ORADATA\REDO03.LOG'  SIZE 500M
DATAFILE
  'C:\ORACLE10G\ORADATA\SYSTEM01.DBF',
  'C:\ORACLE10G\ORADATA\UNDOTBS01.DBF',
  'C:\ORACLE10G\ORADATA\SYSAUX01.DBF',
  'D:\ORADATA\APP_DAT1.DBF',
  ...
CHARACTER SET KO16KSC5601
;

체크포인트 두 가지:

  • DATAFILE 개수가 실제와 일치하는지 세어볼 것. 빠진 파일은 그대로 유실됩니다.
  • CHARACTER SET은 절대 임의로 바꾸지 말 것.

메모장으로 저장할 땐 파일 형식을 "모든 파일"로 바꾸세요. 안 그러면 cf.sql.txt가 됩니다.

5-5. 실행

STARTUP NOMOUNT
@C:\oracle10g\cf.sql
-- 제어 파일이 생성되었습니다.  → 자동으로 MOUNT 상태

6. 여기서 판단 착오 — FUZZY를 안 봤다

3절에서 "SCN이 전부 같으니 복구 불필요"라고 봤기 때문에, 복구 프롬프트에서 그냥 CANCEL을 쳤습니다.

RECOVER DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;
ORA-00279: change 34145857632 (08/03/2026 22:00:04) needed for thread 1
ORA-00289: 제안 : C:\ORACLE10G\RDBMS\ARC00344_1024935211.001
ORA-00280: change 34145857632 for thread 1 is in sequence #344

로그 지정: cancel

ORA-01547: 경고: RECOVER 성공했지만 OPEN RESETLOGS 시 아래 오류 발생
ORA-01194: 파일 1은 더 많은 복구가 필요합니다
ORA-01110: 데이터 파일 1: 'C:\ORACLE10G\ORADATA\SYSTEM01.DBF'
ORA-01112: 미디어 복구가 시작되지 않았습니다

v$datafile_header의 checkpoint SCN이 전부 같다고 해서 일관 상태인 게 아닙니다. FUZZY 플래그가 YES면 redo 적용이 더 필요합니다. 이걸 확인했어야 했습니다.

SELECT DISTINCT fuzzy, status FROM v$datafile_header;

v$recover_file이 비어 있던 것도, 원래 컨트롤파일 기준으로는 "미디어 복구 대상 파일이 없다"는 뜻이지 "redo 적용이 끝났다"는 뜻이 아닙니다.

7. 해결 — 온라인 redo 로그를 직접 지정

ORA-00280을 다시 읽어보면 답이 있습니다.

change 34145857632 for thread 1 is in sequence #344

필요한 redo가 시퀀스 344, 즉 CURRENT였던 REDO02.LOG 안에 그대로 있습니다. NOARCHIVELOG라 아카이브 파일(ARC00344_...)은 존재하지 않지만, 온라인 로그 파일 경로를 직접 입력하면 됩니다.

RECOVER DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;

프롬프트에서 CANCEL 대신:

로그 지정: C:\ORACLE10G\ORADATA\REDO02.LOG
Log applied.
Media recovery complete.
ALTER DATABASE OPEN RESETLOGS;
-- 데이타베이스가 변경되었습니다.

ALTER TABLESPACE TEMP ADD TEMPFILE 'C:\ORACLE10G\ORADATA\TEMP01.DBF' SIZE 500M REUSE;

정상 오픈됐습니다.

⚠️ 이 방법은 온라인 redo 로그 파일이 살아있어야 성립합니다. "redo 파일을 .old로 옮겨두라"는 조언을 그대로 따랐다가 이 단계에서 막힐 뻔했습니다. RESETLOGS 절차에서 온라인 로그를 치우기 전에, 그 안의 redo가 필요한지 먼저 확인하세요.

8. 오픈 후 정리

-- 즉시 콜드 백업 (RESETLOGS 이전 백업은 더 이상 쓸 수 없음)
SHUTDOWN IMMEDIATE
-- → ORADATA 전체 복사

-- 무결성 확인
SELECT owner, object_type, COUNT(*) FROM dba_objects
 WHERE status='INVALID' GROUP BY owner, object_type;
SELECT tablespace_name, status FROM dba_tablespaces;

-- INVALID 객체 재컴파일
@?/rdbms/admin/utlrp.sql

alert log에 ORA-600이 재발하지 않는지 며칠 지켜보는 것도 필요합니다.

9. 정리하며

진단 흐름

  1. ORA-00600은 인자를 읽는 것에서 시작. [3005], [1], [345], [3]은 "thread 1, 그룹 3, 시퀀스 345"로 곧장 해석됨
  2. v$log와 대조해 인자가 가리키는 지점을 특정
  3. CLEAR LOGFILE로 물리 파일 요인을 배제 → 컨트롤파일 문제로 좁혀짐
  4. 컨트롤파일 재생성
  5. 필요한 redo는 온라인 로그에서 직접 공급

얻은 교훈

  • checkpoint_change#가 같다 ≠ 일관 상태. FUZZY를 같이 봐야 한다
  • ORA-00280의 "is in sequence #N"은 버리는 정보가 아니라 해결의 실마리
  • 복구 절차에서 파일을 치우기 전에, 그 파일이 필요한지부터 확인한다
  • 데이터파일이 여러 드라이브에 흩어져 있으면 콜드 백업 때 전부 챙긴다

근본 문제는 따로 있었다

이번에 정말 위험했던 건 ORA-600 자체가 아니라 NOARCHIVELOG + 백업 부재였습니다. 온라인 로그에 시퀀스 344가 남아 있었던 건 상당 부분 운이었습니다. 로그 스위치 간격이 7/16 → 7/25 → 8/3로 길었던 덕에 필요한 redo가 덮어쓰이지 않았을 뿐, 트랜잭션이 조금만 많았다면 344는 이미 순환되어 사라졌을 겁니다.

  • ARCHIVELOG 모드 전환
  • RMAN 정기 백업 구성
  • 10.2.0.3 / 32-bit Windows는 지원 종료 — 패치 경로가 없으므로 마이그레이션 계획 수립

 

참고

  • ORA-00600의 정확한 인자 의미는 My Oracle Support의 ORA-600/ORA-7445 Lookup Tool에서 조회할 수 있습니다. 이 글의 [3005] 해석은 인자 패턴과 v$log 대조로 역산한 것입니다.
  • 운영 DB라면 어떤 조치든 콜드 백업 확보 후 진행하세요. 특히 NOARCHIVELOG 환경에서 RESETLOGS는 되돌릴 수 없습니다.

 

반응형