백업 — 지운 데이터를 되돌린다 · 베이스 + WAL · 이론
백업은 두 종류다
한 줄 요약
논리 백업은 사진이고, 물리 백업 + WAL 은 영상이다. 사진으로는 "어제 밤 상태" 까지만 갈 수 있고, 영상으로는 "사고 나기 30초 전" 으로 갈 수 있다.
왜 필요한가 — 먼저 두 숫자를 정한다
백업 설계는 도구를 고르는 일이 아니라 두 숫자에 답하는 일이다.
- RPO(복구 시점 목표) — 얼마만큼의 데이터를 잃어도 되는가
- RTO(복구 시간 목표) — 얼마 만에 다시 서비스해야 하는가
하루 한 번 pg_dump 를 뜬다면 RPO 는 24시간이다. 최악의 경우 하루치가 사라진다. 그게 감당 가능한지가 먼저이고, 아니라면 WAL 아카이빙이 필요하다.
RTO 도 잊으면 안 된다. 500GB 짜리 덤프를 복원하는 데 6시간이 걸린다면, 백업이 있어도 6시간 동안 서비스가 멈춘다.
논리 백업 — pg_dump
pg_dump -Fc -d labdb -f labdb.dump # 커스텀 포맷 (압축·병렬 복원 가능)pg_restore -d newdb labdb.dump- 버전·아키텍처를 넘나든다 — 16에서 뜬 덤프를 17에 넣을 수 있다
- 일부만 골라 복원할 수 있다 — 테이블 하나만
- 사람이 읽을 수 있다(
-Fp)
하지만 뜬 그 순간의 사진일 뿐이다. 어제 밤 덤프와 오늘 오후의 사고 사이는 되돌릴 방법이 없다. 그리고 큰 DB 에서는 덤프도 복원도 몇 시간씩 걸린다.
> 덤프는 "이사" 와 "부분 복구" 를 위한 것이고, 재해 복구의 주력이 아니다.
물리 백업 + WAL — PITR
PostgreSQL 은 모든 변경을 먼저 WAL(Write-Ahead Log) 에 쓴다. 데이터 파일보다 WAL 이 먼저다. 그래서 이런 등식이 성립한다.
어느 시점의 데이터 파일 복사본 + 그 뒤의 WAL 전부 = 그 뒤 아무 시점이나이게 PITR(Point-In-Time Recovery) 다. 세 조각이 필요하다.
1. archive_mode = on — 다 쓴 WAL 세그먼트를 안전한 곳으로 복사
2. 베이스 백업 — pg_basebackup 으로 뜬 데이터 디렉터리 통째
3. 복구 설정 — restore_command 로 WAL 을 되먹이고 recovery_target_time 에서 멈춘다
archive_command 의 규칙
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'%p— 원본 경로,%f— 파일 이름- 성공하면 0, 실패하면 0이 아닌 값을 반환해야 한다. 성공했다고 거짓말하면 PostgreSQL 이 그 WAL 을 지우고, 그 구간은 영원히 복구 불가가 된다
test ! -f로 덮어쓰기를 막는다. 같은 이름의 다른 내용을 덮어쓰면 복구가 조용히 깨진다
실패하면 PostgreSQL 은 재시도하면서 WAL 을 지우지 않는다. 아카이브 대상이 가득 차면 pg_wal 이 계속 불어나 결국 디스크가 찬다. pg_stat_archiver.failed_count 를 감시하지 않으면 조용히 커지다 터진다.
복구 절차
# 1. 베이스 백업을 복사한다 (원본은 건드리지 않는다)cp -r /backup/base /var/lib/postgresql/restore# 2. 어디서 멈출지 알려 준다cat > restore/postgresql.auto.conf <<EOFrestore_command = 'cp /archive/%f %p'recovery_target_time = '2026-08-21 16:20:41+00'recovery_target_action = 'promote'port = 5433EOF# 3. 복구 모드로 시작하라는 표시touch restore/recovery.signal# 4. 띄운다pg_ctl -D restore startrecovery.signal 이 있으면 PostgreSQL 은 복구 모드로 뜬다. WAL 을 되먹이다 목표 시점에 도달하면 recovery_target_action 대로 한다.
promote— 승격해서 쓸 수 있게 (기본)pause— 멈춰서 확인할 시간을 준다. 확인 후 결정하고 싶으면 이쪽이 안전하다
복구할 때 반드시 지킬 것
절대 원본 위에 복구하지 않는다. 다른 디렉터리·다른 포트에 띄워 확인한 뒤 옮긴다. 복구 대상 시각을 잘못 잡았을 때 되돌릴 여지가 남는다.
타임라인이 갈라진다. 복구 후 승격하면 타임라인 번호가 1 증가한다(00000002...). 원본과 복구본은 그 시점부터 다른 역사다. 이걸 모르면 나중에 "WAL 이 안 맞는다" 로 헤맨다.
자주 하는 실수
백업을 같은 디스크에 둔다. 디스크가 죽으면 둘 다 죽는다. 백업은 다른 장비, 되도록 다른 위치에 있어야 한다.
복원 연습을 안 한다. 이게 가장 흔하고 가장 비싸다. 백업 잡이 초록불인 것과 그 백업으로 복구가 되는 것은 별개다. 정기적으로 복구 리허설을 하지 않으면 백업이 있다고 말할 수 없다.
archive_command 실패를 안 본다. 위에 적은 대로 디스크가 찬다.
논리 백업만 둔다. RPO 가 하루라는 뜻인데, 대개 그렇게 합의한 적이 없다.
실무에서는 도구를 쓴다
직접 스크립트를 짜는 대신 pgBackRest 나 Barman 을 쓴다. 증분 백업, 병렬 압축, 보존 정책, S3 업로드, 그리고 무엇보다 백업 검증이 들어 있다. 이 실습은 그 도구들이 안에서 무엇을 하는지 보기 위한 것이다.
한 줄로 요약하면 이렇다.
> 복구해 본 적 없는 백업은 백업이 아니다.