검사점 회복 기법
더 많은 작업
- 체크포인트(Checkpoint) 회복 기법이라고도 한다.
- 장애 발생 시 검사점(Checkpoint) 이전에 처리된 트랜잭션은 회복에서 제외하고
- 검사점 이후에 처리된 트랜잭션은 회복 작업 수행
- 검사점 이후, 장애 발생 이전에 commit이 완료된 경우 Redo 수행
- 장애 발생 시점까지 commit되지 못한 경우 Undo 수행
- Undo(로그 역순) 수행 후 Redo(로그 순) 수행
검사점은 평소 운영 중에 기록하고, 회복은 장애 뒤에 한다. 시간 순서로 보면 다음과 같다.
- 검사점 기록(평소) - 실행 중인 트랜잭션을 잠시 멈추고, 메모리에서 변경된 데이터 버퍼 블록을 모두 디스크에 강제로 쓰고, 그때 실행 중이던 트랜잭션 목록을 담은 검사점 레코드를 로그에 쓴 뒤(로그도 디스크에 강제 기록) 트랜잭션을 다시 진행한다.[1] 그래서 검사점 전에 커밋한 트랜잭션은 회복할 것이 없다
- 목록 만들기(장애 뒤) - 가장 최근 검사점 레코드에 적힌 실행 중 트랜잭션을 UNDO-list 에 넣고, 로그를 검사점부터 끝까지 읽으며 <T, Start> 를 만나면 T 를 UNDO-list 에 더하고, <T, Commit> 을 만나면 T 를 UNDO-list 에서 빼 REDO-list 로 옮긴다
- UNDO - UNDO-list 에 남은(커밋하지 못한) 트랜잭션의 변경을 로그를 거꾸로 읽으며 이전 값으로 되돌린다
- REDO - REDO-list 의 트랜잭션이 한 변경을 검사점부터 로그 순서대로 다시 적용한다
엘마스리 계열의 즉시 갱신 회복도 미완료 트랜잭션의 쓰기를 로그 역순으로 먼저 취소한 뒤, 커밋된 트랜잭션의 쓰기를 로그 순서대로 재수행하는 순서로 설명한다.[2]
- 목록이 있어야 무엇을 취소하고 무엇을 재수행할지 알 수 있으므로, UNDO·REDO 는 언제나 목록 만들기 뒤에 온다. 버퍼 블록의 디스크 출력은 회복 단계가 아니라 검사점을 기록하는 평소 작업이다
- 실버샤츠(Silberschatz) 7판처럼 '이력 되풀이'(repeating history)를 쓰는 방식은 순서가 다르다. 검사점부터 앞으로 읽으며 모든 변경을 먼저 재수행(redo 단계)하면서 UNDO-list 를 만들고, 그다음 로그를 거꾸로 읽어 미완료 트랜잭션만 취소(undo 단계)한다.[3] ARIES 회복 기법이 이 방식이다
검사점을 기록할 때 그때까지의 수정 내용이 디스크에 쓰이므로, 검사점 이전에 끝난(커밋 또는 철회) 트랜잭션은 회복할 것이 없다. 회복은 로그를 거슬러 가장 최근 검사점 레코드를 찾고, 검사점 때 실행 중이던 트랜잭션과 그 뒤에 시작한 트랜잭션만 다시 하거나(Redo) 취소한다(Undo).[4]
| 시작 | 끝 | 회복 작업 |
|---|---|---|
| 검사점 전 | 검사점 전에 커밋 | 없음(회복에서 제외) |
| 검사점 전 | 검사점 뒤, 장애 전에 커밋 | Redo |
| 검사점 뒤 | 장애 전에 커밋 | Redo |
| 검사점 전 | 장애 때까지 미완료 | Undo |
| 검사점 뒤 | 장애 때까지 미완료 | Undo |
검사점을 기록하는 순간 메모리의 로그 레코드와 수정된 버퍼 블록이 모두 디스크에 기록되고, 그동안은 갱신을 멈춘다.[4] 그래서 회복할 때 두 작업이 로그를 읽는 범위가 다르다.
- Redo 는 검사점부터 - 검사점 이전의 갱신은 이미 디스크에 반영되어 있으므로, Silberschatz 의 회복 알고리즘은 마지막 <checkpoint L> 레코드를 찾아 그 지점부터 앞으로(forward) 로그를 훑으며 다시 한다.[4] 검사점 전에 시작해 검사점 뒤·장애 전에 커밋한 트랜잭션도 검사점 이후의 연산만 Redo 하면 된다. "처음부터 끝까지 Redo 한다"는 틀린 설명이다
- Undo 는 트랜잭션 시작까지 - 장애 때까지 끝나지 않은 트랜잭션은 검사점 전에 디스크에 쓰인 갱신까지 모두 되돌려야 원자성이 지켜진다. 그래서 로그를 끝에서 뒤로(backward) 훑어 그 트랜잭션의 <T start> 레코드를 만날 때까지, 곧 처음부터 끝까지 Undo 한다[4]
- 회복 중에는 새 트랜잭션을 받지 않는다 - Undo 단계까지 마친 뒤에야 정상 트랜잭션 처리를 다시 시작한다[4]
엘마스리(Elmasri)와 나바스(Navathe)도 검사점 때 수정된 버퍼를 디스크에 강제로 쓰므로, 검사점 전에 커밋한 트랜잭션의 쓰기 연산은 시스템 장애 뒤 다시 할 필요가 없다고 설명한다.[5]
예 - 검사점 C1 은 정상 수행되고 다음 검사점 C2 를 수행하던 중 장애가 났다. T1 은 C1 전에 시작·완료, T2 는 C1 전에 시작해 C2 전에 완료, T3 은 C1 전에 시작해 장애 때 실행 중이었다.
| 트랜잭션 | 회복 작업 |
|---|---|
| T1 | 없음(C1 때 이미 디스크에 반영) |
| T2 | C1 이후의 연산만 Redo |
| T3 | 시작부터 장애 시점까지 전부 Undo(C1 전의 갱신 포함) |
회복이 끝날 때까지 새 트랜잭션은 받지 않는다.
검사점 회복은 즉시 갱신이나 지연 갱신과 함께 쓴다. Redo 대상은 같고 Undo 가 필요한지만 다르다.
- 즉시 갱신 - 커밋 전의 변경도 데이터베이스에 쓰이므로, 장애 때 미완료인 트랜잭션은 Undo, 검사점 이후 장애 전에 커밋한 트랜잭션은 Redo 한다
- 지연 갱신 - 커밋하기 전에는 데이터베이스에 쓰지 않으므로 미완료 트랜잭션은 Undo 할 것이 없다(로그만 버린다). 검사점 이후 장애 전에 커밋한 트랜잭션만 Redo 한다
예 - 검사점 뒤에 시스템 고장이 났다. T1 은 검사점 전에 시작해 고장 뒤까지 끝나지 않았고, T2 는 검사점 전에 끝났고, T3 는 검사점 전에 시작해 검사점 뒤·고장 전에 커밋했고, T4 는 검사점 뒤에 시작해 고장 때까지 끝나지 않았다.
| 트랜잭션 | 즉시 갱신 | 지연 갱신 |
|---|---|---|
| T1(미완료) | Undo | 없음 |
| T2(검사점 전 완료) | 없음 | 없음 |
| T3(검사점 뒤 커밋) | Redo | Redo |
| T4(미완료) | Undo | 없음 |
두 방식 모두 Redo 하는 것은 T3 하나다. T2 는 검사점 때 이미 디스크에 반영되어 어느 방식에서도 회복 대상이 아니다.
- ↑ Ramez Elmasri, Shamkant B. Navathe, 「Chapter 22: Database Recovery Techniques」 강의 슬라이드, Pearson, 2016(Purdue University CS448 게시본), https://www.cs.purdue.edu/homes/bb/cs448_Fall2017/lpdf/Chapter22.pdf, 확인일: 2026-11-04.
- ↑ 「Chapter 14. Backup and Recovery」, University of Cape Town Database Systems 강의 노트, https://www.cs.uct.ac.za/mit_notes/database/htmls/chp14.html, 확인일: 2026-11-04.
- ↑ Silberschatz, Korth, Sudarshan, 「Database System Concepts 7th Edition - Chapter 19: Recovery System」 강의 슬라이드, https://www.db-book.com/slides-dir/PDF-dir/ch19.pdf, 확인일: 2026-11-04.
- ↑ 4.0 4.1 4.2 4.3 4.4 4.5 4.6 Silberschatz, Korth, Sudarshan, 「Database System Concepts 7th Edition - Chapter 19: Recovery System」 강의 슬라이드, https://www.db-book.com/slides-dir/PDF-dir/ch19.pdf, 확인일: 2026-11-04.
- ↑ Ramez Elmasri, Shamkant B. Navathe, 『Fundamentals of Database Systems』 7판, Pearson, 2016, 22.1.4 Checkpoints in the System Log and Fuzzy Checkpointing.
