데이터베이스 장애 복구: WAL·체크포인트·백업과 RPO·RTO 계산
1장. 백업은 있었는데 주문 데이터가 사라졌다#
운영 서버가 오후 2시 7분에 장애로 멈췄다고 하겠습니다.
관리자는 자신 있게 말합니다.
백업은 있습니다.
복원 작업을 시작합니다.
데이터베이스는 정상적으로 열립니다.
하지만 마지막으로 확인되는 주문은 오후 2시 4분입니다.
장애는 오후 2시 7분에 발생했습니다.
즉 약 3분 동안 처리된 주문이 보이지 않습니다.
게다가 데이터베이스 자체는 오후 2시 20분에 열렸지만 애플리케이션 연결과 결제 연동까지 정상화된 시각은 오후 2시 28분입니다.
이 상황에서는 세 가지를 따로 봐야 합니다.
백업 파일이 존재하는가?
어느 시점까지 데이터를 복구했는가?
서비스는 언제 다시 사용 가능해졌는가?이 세 질문은 서로 다릅니다.
2장. 장애 복구는 장애 종류부터 구분해야 한다#
모든 장애를 같은 방식으로 복구하지 않습니다.
대표적으로 다음과 같이 나눌 수 있습니다.
| 장애 종류 | 예 | 대표 대응 |
|---|---|---|
| 트랜잭션 실패 | 제약조건 오류, 교착 상태 | ROLLBACK·재시도 |
| 프로세스·서버 장애 | 전원 장애, DB 프로세스 종료 | WAL 기반 재시작 복구 |
| 저장 장치 손상 | 데이터파일 손상·디스크 유실 | 백업·보관 로그·복제본 |
| 사용자 실수 | 정상 COMMIT된 DELETE | PITR·과거 데이터 비교·업무 보정 |
예를 들어 사용자가 실수로 다음 SQL을 실행했다고 하겠습니다.
DELETE FROM orders;그리고 COMMIT했습니다.
서버 재시작으로 이 DELETE가 자동 취소되지는 않습니다.
DBMS 입장에서는 정상적으로 확정된 트랜잭션이기 때문입니다.
3장. COMMIT과 데이터 페이지 기록은 같은 순간이 아닐 수 있다#
주문 상태를:
결제대기
↓
결제완료로 바꾼다고 하겠습니다.
메모리의 데이터 페이지가 변경됩니다.
그렇다면 COMMIT할 때 반드시 변경된 데이터 페이지 전체가 저장 장치에 기록되어야 할까요?
일반적으로 그렇지 않습니다.
개념적으로는 다음과 같은 흐름을 생각할 수 있습니다.
flowchart TD
U["데이터 변경"] --> B["메모리 버퍼 페이지 변경"]
U --> W["WAL 생성"]
W --> F["필요한 WAL 안전하게 기록"]
F --> C["COMMIT 성공"]
B --> D["데이터 페이지는 이후 저장 가능"]핵심은 데이터 페이지보다 복구에 필요한 로그가 먼저 안전하게 기록되는 것입니다.
4장. 이것이 Write-Ahead Logging이다#
WAL은 Write-Ahead Logging의 약자입니다.
직역하면:
먼저 로그를 기록한다.
입니다.
중요한 원칙은 다음과 같습니다.
변경된 데이터 페이지를 저장 장치에 기록하기 전에
그 변경을 복구할 수 있는 로그가
먼저 안정적으로 기록되어야 한다.이 순서가 지켜지면 데이터 페이지와 트랜잭션의 확정 시점이 달라도 장애 이후 상태를 복구할 근거가 남습니다.
5장. 계좌 값 하나로 WAL의 필요성을 이해해 보자#
계좌 A의 잔액이 300이라고 하겠습니다.
트랜잭션 T1이 이를 200으로 변경합니다.
A
300 → 200메모리 버퍼에는 이미 200이 있습니다.
하지만 저장 장치의 데이터 페이지에는 여전히 300이 있을 수 있습니다.
이 상태에서 T1이 COMMIT하고 서버가 즉시 꺼졌다고 하겠습니다.
로그가 없다면:
메모리
→ 사라짐
디스크 데이터 페이지
→ 300이므로 확정된 200을 복구하기 어렵습니다.
WAL이 남아 있다면 장애 후 해당 변경을 다시 적용할 수 있습니다.
6장. WAL이 있으면 데이터 페이지를 늦게 기록할 수 있다#
WAL 기반 시스템에서는 데이터 페이지를 변경할 때마다 즉시 디스크에 써야 할 필요가 줄어듭니다.
개념적으로:
변경
↓
WAL 기록
↓
COMMIT
↓
데이터 페이지는 이후 적절한 시점에 기록할 수 있습니다.
이 구조는 성능과 복구 가능성을 함께 고려한 설계입니다.
하지만 다음은 구분해야 합니다.
WAL이 생성됨
WAL이 실제 내구성 조건을 만족하도록 저장됨설정에 따라 커밋 내구성 정책이 달라질 수 있습니다.
7장. 커밋된 거래와 끝나지 않은 거래가 동시에 존재할 수 있다#
다음 두 거래가 있습니다.
T1#
A
300 → 200
COMMITT2#
B
200 → 350
아직 COMMIT 안 함그 순간 서버가 정전됐습니다.
문제는 데이터파일 상태가 다음처럼 되어 있을 수도 있다는 것입니다.
A 페이지
→ 아직 300
B 페이지
→ 이미 350즉:
커밋된 T1 변경은 파일에 없음
미커밋 T2 변경은 파일에 있음이라는 역설적인 상태가 가능할 수 있습니다.
8장. 그래서 REDO와 UNDO 개념이 필요하다#
개념적인 즉시 갱신 복구 모델에서는 다음처럼 생각할 수 있습니다.
| 트랜잭션 | 상태 | 장애 후 필요 작업 |
|---|---|---|
| T1 | COMMIT 완료 | 필요한 변경 REDO |
| T2 | COMMIT 없음 | 미완료 변경 UNDO |
T1의 변경이 데이터파일에 빠졌다면 다시 반영해야 합니다.
REDO
→ 확정된 변경을 다시 적용T2의 미확정 변경이 파일에 들어갔다면 제거해야 합니다.
UNDO
→ 확정되지 않은 변경을 취소다만 이것은 복구 원리를 이해하기 위한 개념입니다.
모든 DBMS가 동일한 방식으로 before-image를 직접 되돌리는 것은 아닙니다.
9장. PostgreSQL의 크래시 복구를 단순한 UNDO 파일 복원으로 보면 안 된다#
PostgreSQL은 WAL 재생과 트랜잭션의 커밋 상태, MVCC 가시성 정보를 이용합니다.
따라서 다음 설명은 지나치게 단순합니다.
서버 재시작
↓
미커밋 행을 모두 before-image로 직접 되돌림PostgreSQL의 실제 복구 구조는 이보다 다릅니다.
이론적인 REDO·UNDO 개념과 특정 제품의 내부 구현을 구분해야 합니다.
10장. WAL에는 단순히 SQL 문장만 저장되는 것이 아니다#
로그를 다음처럼 생각하면 이해하기 쉽습니다.
UPDATE orders ...SQL 텍스트 자체만 저장한다고 생각할 수 있습니다.
하지만 실제 로그 구조는 DBMS 내부 복구에 필요한 정보 중심으로 설계됩니다.
예를 들면 개념적으로:
어떤 데이터 구조가 변경됐는가?
어떤 변경이 발생했는가?
로그의 위치는 어디인가?
이전 로그와 어떤 순서 관계인가?등을 포함할 수 있습니다.
제품마다 WAL 레코드 구조는 다릅니다.
11장. WAL이 있다고 모든 장애에서 자동 복구되는 것은 아니다#
서버 프로세스만 비정상 종료됐다고 하겠습니다.
데이터파일과 WAL 저장소는 정상입니다.
이 경우 WAL을 이용한 재시작 복구가 가능합니다.
하지만 스토리지 자체가 물리적으로 사라졌다고 하겠습니다.
데이터파일
→ 유실
WAL
→ 같은 디스크에 있어 함께 유실그렇다면 로컬 WAL만으로는 아무것도 복구할 수 없습니다.
이때는 별도 백업이나 다른 장소에 보존된 로그가 필요합니다.
12장. WAL과 백업은 역할이 다르다#
WAL:
변경의 복구 기록백업:
데이터베이스 상태를 다시 시작할 기준점이라고 생각할 수 있습니다.
예를 들어:
09:00
기본 백업
09:00~10:00
WAL 보관
10:00
장애라면:
09:00 백업 복원
↓
09:00 이후 WAL 재생
↓
10:00에 가까운 상태 복구가 가능합니다.
13장. 백업만 있고 이후 WAL이 없다면#
백업 시각:
09:00주문 O100이:
09:05
COMMIT됐습니다.
장애:
09:10그런데 09:00 이후 WAL이 보존되지 않았습니다.
백업을 복원하면:
09:00 상태까지만 돌아옵니다.
09:05 주문 O100은 복구되지 않습니다.
따라서:
백업이 있다.
와:
원하는 시점까지 복구할 수 있다.
는 전혀 다른 말입니다.
14장. 체크포인트는 복구 출발 범위를 조절한다#
DBMS가 시작된 이후 로그가 계속 쌓인다고 하겠습니다.
장애가 났을 때 무조건 데이터베이스 생성 시점부터 로그를 모두 다시 읽어야 한다면 재시작이 매우 오래 걸릴 수 있습니다.
체크포인트는 복구에 필요한 기준 정보를 남겨 재시작 시 탐색·재생 범위를 관리하는 데 도움을 줍니다.
개념적으로:
오래된 WAL
────────────
체크포인트
────────────
최근 WAL
────────────
장애복구는 적절한 체크포인트 관련 위치를 기준으로 필요한 WAL을 처리할 수 있습니다.
15장. 체크포인트가 곧 모든 더러운 페이지의 즉시 기록이라는 뜻은 아니다#
고전적인 설명에서는 체크포인트를:
모든 변경 페이지를 디스크에 쓰고 로그를 정리한다.
라고 단순화하기도 합니다.
하지만 현대 DBMS는 더 유연한 체크포인트 방식을 사용할 수 있습니다.
PostgreSQL에서도 체크포인트를:
모든 더러운 페이지 즉시 기록 완료
그리고 이전 WAL 전부 즉시 삭제라고 이해하면 안 됩니다.
복제와 PITR, WAL 보존 정책 등 다른 요구 때문에 필요한 WAL이 계속 유지될 수도 있습니다.
16장. 체크포인트는 백업을 대신하지 않는다#
체크포인트가 방금 완료됐다고 하겠습니다.
그 직후 스토리지 자체가 물리적으로 손상됐습니다.
체크포인트 정보도 같은 저장소에 있었다면 함께 사라질 수 있습니다.
따라서:
체크포인트
=
재시작 복구를 돕는 DB 내부 메커니즘이지:
체크포인트
=
재해 복구용 백업은 아닙니다.
17장. ARIES는 로그 기반 복구를 이해하는 대표적인 이론 모델이다#
데이터베이스 복구 이론에서 자주 등장하는 것이 ARIES입니다.
대표적으로 세 단계로 설명합니다.
Analysis
REDO
UNDO각 단계는 서로 다른 질문을 해결합니다.
18장. Analysis 단계는 장애 순간의 상태를 파악한다#
분석 단계에서는 개념적으로 다음을 확인합니다.
어떤 트랜잭션이 완료됐는가?
어떤 트랜잭션이 진행 중이었는가?
어떤 페이지가 변경되어 있었는가?
어디부터 복구 작업을 시작해야 하는가?예:
T1
→ COMMIT 완료
T2
→ COMMIT 없음이라면 T1은 완료 거래이고 T2는 미완료 거래로 분류할 수 있습니다.
19장. REDO 단계는 필요한 역사를 재현한다#
REDO를 다음처럼만 외우면 부족합니다.
커밋 거래만 다시 실행ARIES의 핵심 개념에서는 필요한 로그 역사를 다시 적용해 장애 직전 상태까지 재현하는 접근을 사용합니다.
그 과정에서 어떤 페이지에 해당 변경이 이미 적용됐는지도 확인합니다.
즉 로그를 봤다고 무조건 같은 변경을 반복해서 덮어쓰는 것이 아닙니다.
20장. UNDO 단계는 끝나지 않은 거래의 효과를 제거한다#
분석 결과 T2가 장애 당시 미완료라고 하겠습니다.
T2의 변경 효과가 데이터 페이지에 반영되어 있다면 최종 상태에서 제거해야 합니다.
개념적으로:
T2 변경
↓
미완료 확인
↓
UNDO합니다.
ARIES에서는 UNDO 진행 자체도 보상 로그 레코드인 CLR로 기록합니다.
21장. CLR은 복구 중 다시 장애가 나도 이어가기 위한 단서다#
복구 과정 중에 또 서버가 꺼질 수도 있습니다.
UNDO를 절반 진행한 상태에서 다시 장애가 발생했다면 처음부터 무엇을 취소했는지 알 수 있어야 합니다.
CLR은 개념적으로:
이 변경의 취소를 이미 수행했다.라는 복구 진행 정보를 남깁니다.
따라서 복구 과정도 다시 복구할 수 있게 만듭니다.
22장. ARIES를 PostgreSQL 내부 구현과 1:1로 대응하면 안 된다#
ARIES는 매우 중요한 복구 모델이지만 다음처럼 설명하면 안 됩니다.
PostgreSQL
=
ARIES의 Analysis → REDO → UNDO를
완전히 동일하게 구현한다.PostgreSQL은 PostgreSQL 고유의 WAL·MVCC·트랜잭션 상태 관리 방식을 사용합니다.
따라서 ARIES는 복구 개념을 이해하는 이론적 틀로 보고 제품 구현은 별도로 이해하는 것이 정확합니다.
23장. 로그 기반 복구와 다른 발상도 있다#
복구에는 WAL 기반 방식 외에도 다른 아이디어가 존재합니다.
대표적인 개념 가운데 하나가 그림자 페이징입니다.
기존 논리 페이지 P가 물리 위치 A를 가리킨다고 하겠습니다.
P
→ A변경할 때 A를 직접 덮어쓰지 않습니다.
새 위치 B에 수정본을 만듭니다.
기존
P → A
변경본
P → B24장. 그림자 페이징에서는 루트 참조 전환이 중요하다#
새 페이지 B가 생성됐지만 아직 공식 루트가 A를 가리킨다면:
현재 유효 데이터
→ A입니다.
COMMIT 과정에서 새로운 페이지 테이블과 루트 참조를 안전하게 전환합니다.
루트
↓
새 페이지 테이블
↓
B이후부터 새 버전이 현재 상태가 됩니다.
핵심은 단순히 새 페이지를 쓰는 것이 아니라 참조 전환을 안전하게 처리하는 것입니다.
25장. 그림자 페이징도 공짜는 아니다#
기존 페이지를 직접 덮지 않는 방식에는 장점이 있지만 다음 비용이 있습니다.
페이지 복사
쓰기 증폭
사용하지 않는 페이지 회수
페이지 테이블 관리
동시 트랜잭션 처리따라서 WAL보다 무조건 단순하거나 빠르다고 할 수는 없습니다.
복구 방식은 저장 엔진 전체 설계와 연결됩니다.
26장. 백업은 종류보다 복원 경로가 더 중요하다#
운영자는 종종 이렇게 말합니다.
전체 백업 있습니다.
증분 백업 있습니다.하지만 실제 복구에서는:
어느 백업부터 복원하는가?
중간 백업이 모두 존재하는가?
파일이 손상되지 않았는가?
이후 로그가 연속적으로 있는가?가 중요합니다.
백업 파일 목록이 많다는 것과 복구 경로가 완성되어 있다는 것은 다릅니다.
27장. 전체 백업은 복원의 기준점을 제공한다#
예를 들어 일요일 00시에 전체 백업을 생성합니다.
일요일 00:00
Full Backup수요일에 장애가 났다면 이 백업을 기준점으로 사용할 수 있습니다.
하지만 수요일까지의 모든 변경을 되살리려면 이후 변경 기록이 필요합니다.
전체 백업
+
증분 백업
+
로그처럼 여러 재료가 필요할 수 있습니다.
28장. 증분·차등 백업은 복원 체인 자체가 중요하다#
예를 들어:
일요일
Full
월요일
Incremental 1
화요일
Incremental 2
수요일
Incremental 3이라고 하겠습니다.
중간 조각이 하나 손상되면 복원 가능한 시점이 달라질 수 있습니다.
따라서 백업 시스템에서는 단순히:
백업 성공만 기록하지 말고:
복원 체인이 실제로 연결되는가?를 시험해야 합니다.
29장. PostgreSQL PITR은 기본 백업과 연속 WAL이 핵심이다#
PITR은 Point-In-Time Recovery의 약자입니다.
특정 시점으로 데이터베이스를 복구하는 방법입니다.
개념적으로:
flowchart LR
B["Base Backup"] --> W1["WAL"]
W1 --> W2["WAL"]
W2 --> W3["WAL"]
W3 --> T["목표 시점"]기본 백업을 복원한 뒤 보관된 WAL을 목표 시점까지 재생합니다.
30장. WAL 하나가 빠지면 목표 시점까지 이어가지 못할 수 있다#
다음 순서가 있다고 하겠습니다.
Backup
↓
WAL 001
↓
WAL 002
↓
WAL 003
↓
목표 시각그런데 WAL 002가 사라졌습니다.
WAL 001
↓
[WAL 002 없음]
↓
WAL 003연속적인 재생이 필요한 구조라면 WAL 003이 있어도 목표 시점까지 정상 복구하지 못할 수 있습니다.
따라서 WAL 아카이브에서는 파일 존재 여부뿐 아니라 연속성이 중요합니다.
31장. 복제본은 백업과 같은 것이 아니다#
운영 DB와 복제 DB가 있다고 하겠습니다.
운영자 실수로:
DELETE FROM customer;를 실행하고 COMMIT했습니다.
복제본이 정상적으로 변경을 따라간다면 이 DELETE도 복제됩니다.
Primary
고객 삭제
↓
Replica
고객 삭제즉 복제본은 장애 대응에 매우 유용하지만 사용자 실수까지 그대로 복제할 수 있습니다.
그래서 백업과 역할이 다릅니다.
32장. 고가용성과 백업은 서로 다른 문제다#
복제본은 다음 목표에 도움이 될 수 있습니다.
서버 장애 시 빠른 전환
읽기 부하 분산백업은 다음 문제를 해결할 수 있습니다.
과거 시점 복원
오래된 데이터 복구
논리적 실수 복구따라서:
Replica 있으니
백업 필요 없음은 위험한 판단입니다.
33장. RPO는 얼마나 많은 데이터를 잃어도 되는가를 나타낸다#
RPO는 Recovery Point Objective입니다.
복구 목표 시점을 뜻합니다.
쉽게 말하면:
장애 발생 시 최대 몇 분 전 데이터까지 잃는 것을 허용할 것인가?
예를 들어:
RPO = 5분이라면 장애 직전 최대 5분 정도의 데이터 손실을 업무가 감당할 수 있다는 목표입니다.
34장. RPO를 실제 시간으로 계산해 보자#
장애 시각:
14:07복구된 마지막 정상 커밋:
14:04이라면 관측된 데이터 손실 간격은:
14:07 - 14:04
=
3분입니다.
목표:
RPO 5분이라면 이 복구 결과는 시간 기준으로 목표 안에 들어갑니다.
35장. 백업 주기와 RPO는 같은 것이 아니다#
매일 자정에 백업한다고 하겠습니다.
00:00
백업그렇다고 반드시 RPO가 24시간인 것은 아닙니다.
백업 이후 변경 로그를 별도로 계속 보관하고 있다면 훨씬 최근 시점까지 복구할 수 있습니다.
반대로 로그가 없다면 자정 백업 이후 데이터는 잃을 수 있습니다.
따라서 RPO는 백업 주기만으로 결정되지 않습니다.
36장. RTO는 언제 서비스를 다시 사용할 수 있는가를 뜻한다#
RTO는 Recovery Time Objective입니다.
쉽게 말하면:
장애 이후 몇 분 안에 서비스를 다시 사용할 수 있어야 하는가?
예:
RTO = 30분이라면 장애 발생 이후 30분 안에 업무를 재개하는 것이 목표입니다.
37장. 데이터베이스가 열렸다고 RTO가 끝난 것은 아닐 수 있다#
장애:
14:07DB 복원 완료:
14:20애플리케이션 정상 접속:
14:24결제 연동 확인:
14:28사용자가 실제 주문을 다시 할 수 있는 시점은:
14:28입니다.
따라서 업무 기준 복구 시간은:
14:28 - 14:07
=
21분으로 기록할 수 있습니다.
38장. DB 프로세스 시작 시각만 RTO로 기록하면 지나치게 낙관적일 수 있다#
다음처럼 기록했다고 하겠습니다.
DB 시작
14:18
RTO
11분하지만 애플리케이션이 14:35까지 연결되지 않았습니다.
실제 사용자는 28분 동안 서비스를 사용할 수 없었습니다.
따라서 복구 훈련에서는:
DB 복구
애플리케이션 연결
외부 서비스 연동
업무 기능 검증까지 포함해 재개 시각을 측정해야 합니다.
39장. RPO와 RTO는 서로 다른 목표다#
다음 사례를 보겠습니다.
장애:
14:00복구 데이터:
13:59까지서비스 재개:
15:00이라면:
RPO
≈ 1분
RTO
≈ 60분입니다.
데이터는 거의 잃지 않았지만 서비스 복구는 매우 느립니다.
반대로:
RPO 30분
RTO 2분인 시스템도 있을 수 있습니다.
빠르게 서비스는 살리지만 일부 최근 데이터를 잃을 수 있습니다.
40장. RPO와 RTO를 제품 이름으로 보장하면 안 된다#
다음처럼 말하면 위험합니다.
복제 사용
→ RPO 0
클러스터 사용
→ RTO 10초실제 값은 다음에 따라 달라집니다.
동기·비동기 복제
복제 지연
장애 감지 시간
승격 절차
DNS·라우팅 전환
애플리케이션 재접속
스토리지 상태
운영자 대응RPO와 RTO는 실제 복구 훈련에서 측정해야 하는 업무 목표입니다.
41장. 실제 복구 훈련 기록지를 만들어 보자#
목표를 다음과 같이 정했다고 하겠습니다.
RPO
5분
RTO
30분훈련 중 다음을 기록합니다.
| 실제 시각 | 작업 | 확인 사항 |
|---|---|---|
| 14:07 | 장애 선언 | 원본 저장소 사용 불가 |
| 14:09 | 백업 복원 시작 | 백업 ID·체크섬 |
| 14:16 | WAL 재생 완료 | 마지막 연속 WAL |
| 14:20 | DB 시작 | SQL 접속 확인 |
| 14:24 | 애플리케이션 연결 | 커넥션 확인 |
| 14:28 | 주문·결제 테스트 성공 | 업무 재개 |
마지막 복구 주문이 14:04라면:
RPO 실측
3분서비스 정상화가 14:28이면:
RTO 실측
21분입니다.
두 목표 모두 만족합니다.
42장. 마지막 WAL이 14시라면 같은 훈련도 실패한다#
장애는 여전히:
14:07입니다.
하지만 마지막으로 복구 가능한 로그가:
14:00까지만 있습니다.
그러면:
14:07 - 14:00
=
7분의 데이터 손실 간격입니다.
목표가 RPO 5분이었다면 실패입니다.
데이터베이스가 10분 만에 열려도 RPO 실패는 그대로입니다.
43장. 반대로 데이터는 다 살렸어도 RTO는 실패할 수 있다#
복구 데이터:
14:06:59까지거의 모든 데이터를 복구했습니다.
RPO는 매우 좋습니다.
하지만 복원·검증·연결 전환에 45분이 걸렸습니다.
목표가:
RTO 30분이라면 실패입니다.
따라서 RPO와 RTO는 항상 별도로 기록해야 합니다.
44장. 백업 성공 여부보다 복원 성공 여부가 중요하다#
백업 시스템이 매일 다음 메시지를 보여준다고 하겠습니다.
Backup completed successfully좋은 신호입니다.
하지만 실제 복원 테스트를 한 번도 해보지 않았다면 다음을 알 수 없습니다.
파일이 실제로 열리는가?
암호화 키가 있는가?
로그 체인이 연결되는가?
필요한 권한이 있는가?
얼마나 오래 걸리는가?
애플리케이션까지 정상화되는가?복구 계획은 복원 훈련을 해봐야 검증됩니다.
45장. 백업 파일도 원본과 같은 장애 영역에만 두면 위험하다#
DB 서버 디스크와 백업 파일이 같은 물리 저장소에 있다고 하겠습니다.
스토리지가 전체 손상되면:
운영 DB
→ 손실
백업
→ 함께 손실이 될 수 있습니다.
따라서 복구 설계에서는 보관 위치까지 고려해야 합니다.
다른 장치
다른 노드
다른 장애 영역
필요한 경우 원격 보관등의 전략을 검토할 수 있습니다.
46장. 사용자 실수는 장애 복구에서 특히 까다롭다#
운영자가 오후 3시에 실수로 중요한 데이터를 삭제했습니다.
DELETE FROM customer
WHERE region = 'SEOUL';그리고 COMMIT했습니다.
오후 3시 5분에 문제를 발견했습니다.
DBMS는 정상적으로 동작하고 있습니다.
서버 장애도 없습니다.
이 경우 단순 크래시 복구는 도움이 되지 않습니다.
DELETE는 정상적으로 커밋되었기 때문입니다.
47장. 데이터베이스 전체를 과거로 돌리는 것이 항상 답은 아니다#
오후 3시 삭제 직전 상태로 전체 DB를 복원할 수 있다고 하겠습니다.
그런데 오후 3시부터 3시 5분 사이 정상 주문 1만 건이 새로 들어왔습니다.
전체 DB를 2시 59분으로 되돌리면 정상 주문까지 사라집니다.
따라서 더 안전한 방법은 상황에 따라:
격리된 복구 환경 생성
↓
삭제 직전 데이터 복원
↓
필요한 행만 추출
↓
현재 운영 DB와 비교
↓
정정 작업일 수 있습니다.
48장. PITR은 운영 DB 전체를 즉시 덮어쓰는 기능으로만 생각하면 안 된다#
시점 복원은 과거 상태를 재현할 수 있는 강력한 도구입니다.
하지만 실제 운영에서는 먼저 별도의 복구 환경에서 원하는 시점의 데이터를 확인하는 것이 안전할 수 있습니다.
특히 일부 데이터만 잘못된 경우에는:
전체 시스템 과거 복원보다:
필요 데이터만 복구·비교·보정이 더 적절할 수 있습니다.
49장. 복구된 주문 한 건을 끝까지 확인해야 한다#
DB가 정상적으로 열렸습니다.
그것만으로 복구 완료라고 선언하지 않는 것이 좋습니다.
예를 들어 마지막 복구 주문을 확인합니다.
주문ID
O20261001-9821다음을 함께 봅니다.
주문 상태
주문항목
결제 상태
재고 상태
고객 정보복구 시점은 단순히 테이블 하나의 마지막 행으로만 판단하면 부족할 수 있습니다.
50장. 업무 데이터 간 일관성도 확인해야 한다#
복구 후 주문은 존재합니다.
ORDER
→ 있음그런데 결제 정보가 없습니다.
PAYMENT
→ 없음또는 재고는 이미 줄어 있습니다.
이 경우 데이터베이스는 열렸지만 업무 상태는 불완전할 수 있습니다.
따라서 복구 검증에는 대표적인 업무 트랜잭션의 관련 데이터를 함께 확인하는 것이 좋습니다.
51장. 재난 복구에서는 애플리케이션 전환까지 포함해야 한다#
대기 데이터베이스를 승격했다고 하겠습니다.
DB 자체는 정상입니다.
하지만 애플리케이션의 접속 주소가 여전히 장애난 서버를 가리키고 있다면 사용자는 서비스를 이용할 수 없습니다.
대기 DB 승격
↓
연결 주소 변경
↓
커넥션 재생성
↓
애플리케이션 정상화이 전체가 실제 서비스 복구 흐름입니다.
52장. PostgreSQL PITR 복구 구조를 개념적으로 정리하면#
flowchart TD
B["Base Backup"] --> R["복원 환경"]
A["Archived WAL"] --> R
R --> P["목표 시점까지 WAL 재생"]
P --> V["데이터 검증"]
V --> S["서비스 전환"]각 단계마다 실패 가능성이 있습니다.
백업 손상
WAL 누락
목표 시점 오류
설정 누락
애플리케이션 연결 실패따라서 단계별 검증이 필요합니다.
53장. RPO 계산에서는 마지막으로 복구 가능한 커밋을 기준으로 보자#
장애 시각:
16:20복원된 마지막 정상 주문:
16:17이면:
관측 손실 간격
=
3분입니다.
중요한 것은:
마지막 백업 시각이 아니라:
실제로 복구된 마지막 업무 데이터의 시각입니다.
54장. RTO 계산에서는 마지막으로 정상 업무가 가능해진 시각을 본다#
장애:
16:20DB 복원:
16:35애플리케이션 시작:
16:40첫 정상 주문 처리:
16:44이면 업무 기준 RTO 실측은:
16:44 - 16:20
=
24분으로 볼 수 있습니다.
DB 엔진이 15분 만에 켜졌다는 것만으로 끝나지 않습니다.
55장. 체크포인트를 자주 만들면 무조건 좋은 것도 아니다#
체크포인트가 너무 드물면 재시작 시 처리해야 할 WAL 범위가 커질 수 있습니다.
반대로 지나치게 빈번하면 더러운 페이지 기록이 자주 발생하면서 I/O 부하가 증가할 수 있습니다.
따라서:
복구 시간
쓰기 부하
스토리지 성능
WAL 생성량등을 함께 고려해야 합니다.
체크포인트 주기를 단순히 짧을수록 좋다고 볼 수 없습니다.
56장. WAL 보존량도 무조건 많다고 좋은 것은 아니다#
오랜 기간 WAL을 보존하면 더 먼 과거로 PITR할 수 있는 가능성이 커집니다.
하지만 저장 공간이 필요합니다.
또 관리와 아카이브 정책이 필요합니다.
반대로 너무 빨리 삭제하면 필요한 시점의 복구 재료가 사라질 수 있습니다.
따라서 WAL 보존은 다음 목표와 연결해야 합니다.
원하는 PITR 범위
RPO
백업 주기
스토리지 용량57장. 복구 전략은 장애 유형별로 달라야 한다#
트랜잭션 오류#
ROLLBACK
재시도서버 크래시#
WAL 기반 재시작 복구디스크 유실#
백업
+
보관 로그
+
필요하면 복제본사용자 실수#
PITR
과거 데이터 비교
업무 보정사이트 전체 장애#
다른 장애 영역의 시스템
+
애플리케이션 연결 전환하나의 복구 기술로 모든 문제를 해결할 수 없습니다.
58장. 백업과 고가용성 기술의 역할을 혼동하면 안 된다#
예를 들어 Oracle 환경에서는 다음과 같은 여러 기술을 접할 수 있습니다.
RMAN
Flashback
Data Guard
RAC
GoldenGate각각 해결하는 문제의 범위가 다릅니다.
RMAN은 백업·복구와 관련된 도구입니다.
Flashback 계열 기능은 과거 데이터 조회나 특정 복원 시나리오에 사용할 수 있습니다.
Data Guard는 대기 데이터베이스와 재해 복구에 관련됩니다.
RAC는 여러 인스턴스를 이용한 가용성·확장 구조입니다.
GoldenGate는 변경 데이터 복제와 이관 등에 활용됩니다.
이 기능들을 모두 “백업 기술”이라고 묶으면 안 됩니다.
59장. 특정 제품의 명령어를 다른 DBMS에서 그대로 사용할 수 없다#
예를 들어:
RMAN> BACKUP DATABASE;는 Oracle RMAN 명령입니다.
또:
FLASHBACK TABLE계열도 Oracle 기능입니다.
PostgreSQL에서 동일한 명령을 실행할 수 있는 것은 아닙니다.
복구 원리는 공통적으로 비교할 수 있지만 실제 명령과 기능은 제품별로 확인해야 합니다.
60장. 복구 목표를 세울 때 비용도 함께 달라진다#
다음 두 목표를 비교해 보겠습니다.
시스템 A#
RPO
24시간
RTO
8시간시스템 B#
RPO
0에 가까움
RTO
수분시스템 B는 더 강한 복제와 자동 전환, 로그 보존, 모니터링, 운영 자동화 등이 필요할 가능성이 큽니다.
따라서 낮은 RPO와 RTO는 기술뿐 아니라 비용과 운영 복잡도를 증가시킬 수 있습니다.
61장. 모든 데이터를 같은 RPO·RTO로 보호할 필요도 없다#
예를 들어 회사 시스템에는 다음 데이터가 있습니다.
결제
주문
게시판
검색 로그
추천 통계결제와 주문은 데이터 손실 허용 범위가 매우 작을 수 있습니다.
검색 로그는 일부 손실을 허용할 수도 있습니다.
따라서 데이터와 서비스의 중요도에 따라 복구 목표를 다르게 설계할 수 있습니다.
62장. 복구 훈련에서 꼭 남겨야 할 증거#
복구 훈련을 수행했다면 다음을 기록하는 것이 좋습니다.
사용한 백업 ID
백업 생성 시각
백업 체크섬
사용한 WAL 범위
마지막 복구 트랜잭션
마지막 복구 주문ID
복원 시작 시각
DB 기동 시각
애플리케이션 연결 시각
업무 테스트 완료 시각이 기록이 있어야 다음 훈련과 실제 결과를 비교할 수 있습니다.
63장. “복구 성공”을 한 문장으로 기록하지 말자#
다음 기록은 정보가 부족합니다.
복구 성공대신 다음처럼 작성할 수 있습니다.
장애 가정
14:07
마지막 복구 주문
14:04:22
관측 데이터 손실
2분 38초
DB 기동
14:20
주문 API 정상
14:28
업무 복구 시간
21분이렇게 기록하면 RPO와 RTO를 실제 목표와 비교할 수 있습니다.
64장. 복구 테스트는 정상 주문 하나를 새로 넣어보는 것까지 포함할 수 있다#
복원된 DB를 읽는 데 성공했다고 끝내지 않고 새로운 테스트 주문을 처리해 봅니다.
회원 조회
↓
상품 조회
↓
주문 생성
↓
결제 상태 기록
↓
조회 확인이 과정이 정상적으로 완료되어야 실제 업무를 재개할 수 있다고 판단할 수 있습니다.
65장. 장애 복구 전체 흐름을 정리하면#
flowchart TD
A["장애 발생"] --> B{"장애 유형 확인"}
B -->|"서버 장애"| C["WAL 재시작 복구"]
B -->|"스토리지 손상"| D["백업 복원"]
B -->|"사용자 실수"| E["PITR·과거 데이터 복원"]
D --> F["보관 WAL 재생"]
E --> F
C --> G["데이터 검증"]
F --> G
G --> H["애플리케이션 연결"]
H --> I["업무 기능 확인"]
I --> J["RPO·RTO 실측"]복구는 파일을 열어보는 단계에서 끝나지 않습니다.
66장. 복구 계획 체크리스트#
- 어떤 장애까지 보호하려는가?
- 운영 DB와 백업이 같은 장애 영역에만 있지 않은가?
- 마지막 정상 백업은 언제인가?
- 백업은 실제로 복원해 보았는가?
- 백업 이후 WAL이나 변경 로그가 연속적으로 존재하는가?
- 원하는 시점까지 PITR할 수 있는가?
- 복제 지연은 어느 정도인가?
- 사용자 실수가 복제본에도 그대로 전달되는가?
- 장애 발생 시 누가 복구를 시작하는가?
- 연결 전환 절차는 자동인가 수동인가?
- 마지막 복구 데이터는 어떤 업무 ID로 확인하는가?
- 데이터베이스 기동 뒤 애플리케이션까지 확인하는가?
- 실제 RPO를 측정했는가?
- 실제 RTO를 측정했는가?
- 복구 훈련 결과를 정기적으로 비교하는가?
67장. 핵심 정리#
데이터베이스 장애 복구에서 가장 먼저 구분해야 할 것은 다음입니다.
서버가 멈춘 것
저장 장치가 손상된 것
사용자가 잘못된 변경을 COMMIT한 것세 상황의 대응은 서로 다릅니다.
WAL의 핵심 원칙은 데이터 페이지보다 복구에 필요한 로그를 먼저 안전하게 기록하는 것입니다.
그래서 COMMIT된 데이터 페이지가 아직 저장되지 않았더라도 로그를 이용해 변경을 복구할 수 있습니다.
반대로 미확정 변경의 일부가 데이터 페이지에 존재하는 상황도 복구 알고리즘이 고려해야 합니다.
개념적으로:
확정 변경이 빠짐
→ REDO
미확정 변경이 남음
→ UNDO 개념으로 이해할 수 있습니다.
ARIES에서는 이를:
Analysis
↓
REDO
↓
UNDO의 세 단계로 설명할 수 있지만 모든 DBMS가 이 절차를 그대로 구현한다고 보면 안 됩니다.
체크포인트 역시:
백업이 아닙니다.
재시작 복구의 기준을 관리하는 내부 메커니즘이며 저장소 전체 손상에서는 별도의 백업이 필요합니다.
PostgreSQL에서 특정 시점 복구를 하려면 기본 백업과 필요한 WAL이 연속적으로 보존되어 있어야 합니다.
Base Backup
+
Archived WAL
=
PITR의 기반입니다.
복제본도 백업과 같지 않습니다.
잘못된 DELETE가 정상적으로 복제되면 복제본에서도 같은 데이터가 사라질 수 있습니다.
그리고 복구 능력은 RPO와 RTO로 나누어 봐야 합니다.
RPO
→ 어디까지의 데이터 손실을 허용할 것인가?
RTO
→ 얼마 안에 서비스를 다시 사용할 수 있어야 하는가?예를 들어:
장애
14:07
마지막 복구 데이터
14:04
서비스 재개
14:28이라면:
관측 RPO
≈ 3분
관측 RTO
≈ 21분입니다.
마지막으로 가장 중요한 원칙은 이것입니다.
백업이 있다는 사실은 복구할 수 있다는 증거가 아니다.
실제 복구 환경에서 백업을 열고, 필요한 WAL을 적용하고, 마지막 주문과 결제 상태를 검증하고, 애플리케이션이 다시 요청을 처리하는 시점까지 확인해야 합니다.
그리고 그 과정에서:
얼마의 데이터를 잃었고, 얼마 만에 업무가 다시 가능해졌는가?
를 실제 시간으로 기록해야 합니다.
그 기록이 있어야 백업 정책이 단순한 파일 보관이 아니라 검증된 복구 전략이 됩니다.