DB Study

7장. Redo · 커밋 · 인스턴스 복구

전원이 뽑혀도 커밋된 데이터는 살아남는다 — 그 약속을 지키는 것이 redo입니다. COMMIT 한 번이 디스크까지 가는 여정과, 크래시 후 Oracle이 스스로 일어서는 2단계 복구를 봅니다.

중급 ⏱ 약 30분 🎬 애니메이션 3개 선수 지식: 4장 백그라운드 프로세스, 6장 Undo
🧭
이 장에서 배우는 것

① redo의 생성 경로 — log buffer → LGWR → online redo log ② COMMIT의 실제 동작과 log file sync 대기 ③ log switch · ARCHIVELOG · checkpoint ④ 인스턴스 크래시 복구 2단계: roll forward(redo 재생) → rollback(undo로 미커밋 취소)

7.1 Redo란 — 모든 변경의 일기장

6장의 undo가 "되돌리기 위한" 데이터라면, redo는 "다시 하기(re-do) 위한" 데이터입니다. 데이터 블록에 가해지는 모든 변경은 그 변경을 재현할 수 있는 redo record로 먼저 기록됩니다. 테이블 블록 변경도, 인덱스 블록 변경도, 심지어 undo 블록 변경도 redo에 남습니다.

왜 이런 이중 기록을 할까요? Buffer Cache의 변경된(dirty) 블록을 매번 디스크에 쓰는 것은 느립니다 — 블록이 datafile 여기저기에 흩어져 있어 랜덤 I/O이기 때문입니다. 반면 redo는 로그 파일 끝에 이어 쓰기만 하는 순차 I/O라 빠릅니다. 그래서 Oracle의 전략은:

💡
Write-Ahead의 철학

"변경의 기록(redo)만 빠르게 디스크에 확정하고, 실제 블록 쓰기는 DBWn이 나중에 천천히." 크래시가 나도 일기장(redo)만 있으면 블록을 다시 만들 수 있으니까요. PostgreSQL의 WAL(Write-Ahead Log)과 완전히 같은 철학입니다 — PostgreSQL 9장과 비교해 보세요.

redo가 흐르는 경로는 세 정거장입니다.

7.2 COMMIT 한 번의 여정 — 커밋은 왜 빠른가

많은 분들이 오해합니다. "커밋하면 변경된 데이터가 디스크에 저장된다"고요. 사실 커밋 시점에 디스크에 확실히 쓰이는 것은 데이터 블록이 아니라 redo입니다.

세션: UPDATE 후 COMMIT COMMIT → SCN 확정 SGA (메모리) Buffer Cache dirty 블록 (bal=200) 아직 메모리에만 있음 Redo Log Buffer redo record: bal 100→200 LGWR 기상! ⏰ Online Redo Log 💾 순차 쓰기 (빠름) 세션은 대기: log file sync ⏳ 쓰기 완료 → "커밋 성공" 응답 ✅ dirty 블록은 아직 메모리에! DBWn이 나~중에 여유롭게 씀 (체크포인트)

LGWR가 log buffer를 디스크로 내리는 계기는 커밋만이 아닙니다.

⚠️
건별 커밋은 log file sync 폭탄

루프 안에서 1건 처리할 때마다 커밋하면, 매번 LGWR의 디스크 쓰기를 기다립니다. 10만 건이면 10만 번의 동기 I/O 대기죠. 배치 작업은 모아서 커밋하는 것이 기본입니다. AWR에서 log file sync가 상위 대기 이벤트라면 과도한 커밋 빈도나 느린 redo 디스크를 의심하세요.

7.3 Log Switch와 ARCHIVELOG — 일기장 돌려쓰기

online redo log는 최소 2개의 그룹이 원형으로 돌아가며 쓰입니다. 현재 그룹이 가득 차면 다음 그룹으로 넘어가는 것이 log switch입니다. 그런데 한 바퀴 돌아 다시 첫 그룹을 덮어써야 할 때, 그 안의 redo가 지워지면 그 시점 이전으로의 복구 능력도 사라집니다. 그래서 운영 DB는 ARCHIVELOG 모드를 켜고, 덮어쓰기 전에 ARCn 프로세스가 사본(archived log)을 떠 둡니다.

Group 1 ✍️ CURRENT (쓰는 중) 가득 참 → ACTIVE 아카이브 완료 → 재사용 OK ♻️ Group 2 ✍️ CURRENT (log switch!) Group 3 ✍️ CURRENT ARCn 🗃️ archived log: arch_0001.arc 백업/PITR 복구의 재료 online redo log 그룹은 최소 2개 — 원형으로 돌려쓴다
-- redo log 그룹 상태 확인
SELECT group#, status, bytes/1024/1024 AS mb, archived
FROM   v$log;

GROUP#  STATUS    MB   ARCHIVED
------  --------  ---  --------
     1  INACTIVE  200  YES      ← 아카이브 완료, 재사용 가능
     2  CURRENT   200  NO       ← LGWR가 지금 쓰는 중
     3  ACTIVE    200  YES      ← 체크포인트 미완료, 아직 복구에 필요

-- 아카이브 모드 확인 / 수동 log switch
ARCHIVE LOG LIST;
ALTER SYSTEM SWITCH LOGFILE;
🚨
아카이브가 밀리면 DB가 멈춘다

archived log를 쓸 디스크가 가득 차면 ARCn이 멈추고, 아카이브 안 된 그룹은 재사용할 수 없으므로 결국 LGWR도 멈춥니다. 증상은 모든 세션이 매달리는 대기와 alert log의 "all online logs needed archiving". 아카이브 영역 공간 모니터링은 Oracle 운영의 기본 중 기본입니다.

7.4 Checkpoint — 복구 시작선을 앞으로 당기기

Checkpoint는 "여기까지의 변경은 datafile에 확실히 반영되었다"는 동기화 지점입니다. DBWn이 그 시점까지의 dirty 블록을 디스크에 쓰고, CKPT 프로세스가 컨트롤 파일과 datafile 헤더에 체크포인트 위치(SCN)를 기록합니다.

체크포인트가 중요한 이유는 단 하나 — 크래시 복구를 어디서부터 시작할지를 정하기 때문입니다. 체크포인트 이전의 redo는 이미 datafile에 반영됐으니 재생할 필요가 없습니다. 체크포인트가 자주 진행될수록 복구는 빨라지고, 대신 평상시 디스크 쓰기는 늘어납니다. 이 균형은 FAST_START_MTTR_TARGET(목표 복구 시간, 초 단위) 파라미터로 조절합니다.

7.5 인스턴스 복구 — 크래시에서 스스로 일어서는 2단계

전원 장애로 인스턴스가 즉사했다고 합시다. 그 순간 디스크의 상태는 엉망입니다.

다음 기동 때 SMON이 이 둘을 정리합니다. 무기는 redo와 undo, 순서는 정확히 2단계입니다.

⚡ 크래시! 인스턴스(메모리) 증발 재기동 — SMON이 복구 시작 Datafiles (크래시 직후) TX1 (커밋됨): 변경이 파일에 없음 😱 TX2 (미커밋): 변경이 파일에 있음 😱 TX0 (커밋+반영 완료): 문제 없음 Online Redo Log 체크포인트 이후의 모든 변경 기록 (TX1, TX2의 redo + undo 블록의 redo) 1단계 roll forward ▶ TX1 (커밋됨): redo 재생으로 복원 ✅ Undo (roll forward로 복원됨) TX2의 before image 2단계 rollback ◀ TX2 (미커밋): undo로 취소 ↩️ ✅ 복구 완료: 커밋된 것은 전부 살고, 미커밋은 전부 사라졌다 — 원자성과 내구성의 증명
💡
왜 "redo 먼저, undo 나중"인가

undo 자체도 데이터 블록이라(6장) 크래시로 최신 undo가 디스크에 없을 수 있습니다. 그래서 redo 재생으로 undo부터 되살린 다음에야 그 undo로 미커밋을 되돌릴 수 있습니다. "redo가 undo를 복원하고, undo가 트랜잭션을 되돌린다" — 이 한 문장이 Oracle 복구의 전부입니다.

7.6 PostgreSQL WAL과 나란히 놓고 보기

같은 write-ahead 철학이라 대응 관계가 깔끔합니다. PostgreSQL을 아는 분이라면 이 표 하나로 이 장을 복습할 수 있습니다 (PostgreSQL 9장 WAL과 Checkpoint).

역할OraclePostgreSQL
변경 로그redo (online redo log)WAL 세그먼트
로그 쓰기 프로세스LGWRwalwriter (+ 커밋 시 백엔드 직접)
커밋 대기 이벤트log file syncWALWrite / fsync 대기
로그 파일 운용고정 그룹 순환 + 아카이브세그먼트 생성·재활용 + archive_command
미커밋 취소 정보undo (별도 저장소, 복구 2단계에 필수)불필요 — 옛 버전이 heap에 남아 있어 롤백이 저렴
크래시 복구roll forward(redo) → rollback(undo)REDO 지점부터 WAL 재생 (undo 단계 없음)

가장 큰 차이는 마지막 줄입니다. PostgreSQL은 미커밋 변경도 "새 버전 튜플"일 뿐이라 복구에서 되돌릴 것이 없습니다(커밋 안 된 XID의 튜플은 그냥 안 보임). Oracle은 제자리 수정 구조라 undo를 이용한 rollback 단계가 반드시 필요합니다 — 6장에서 본 구조 차이가 복구 절차의 차이로 그대로 이어지는 것이죠.

✍️ 이해도 체크

COMMIT이 성공적으로 반환된 직후의 상태로 옳은 것은?
✅ 커밋 시 디스크에 확정되는 것은 redo뿐입니다(LGWR의 쓰기 완료 = log file sync 대기 종료). 데이터 블록은 DBWn이 나중에 씁니다. 크래시가 나도 redo로 재현할 수 있으므로 내구성은 보장됩니다. undo도 읽기 일관성을 위해 당분간 보존됩니다(6장).
인스턴스 복구에서 roll forward가 rollback보다 먼저 수행되어야 하는 이유는?
✅ undo도 데이터 블록이므로 크래시로 최신 상태가 디스크에 없을 수 있습니다. roll forward가 redo를 재생해 undo까지 크래시 직전 상태로 복원한 뒤에야, 그 undo로 미커밋 트랜잭션을 되돌릴(rollback) 수 있습니다. 참고로 DB는 roll forward 후 바로 열리고 rollback은 백그라운드로 계속됩니다.
📚
원문으로 더 깊이

Oracle Database 19c Concepts Guide: Physical Storage Structures (online redo log 구조) · Oracle Database Instance (인스턴스 복구 절차와 체크포인트) — SCN, thread, 멀티플렉싱 등 심화 내용이 있습니다.