PostgreSQLSeniorSystem design

Что такое PITR (point-in-time recovery)? Как её настроить? Что такое base backup + WAL archive?

PITR восстанавливает кластер на произвольный момент: берут base backup (pg_basebackup или pgBackRest), непрерывно архивируют WAL (archive_command → S3), при восстановлении задают recovery_target_time и replay-ят архив через restore_command.

Что такое PITR

Point-in-time recovery (PITR) — механизм восстановления кластера PostgreSQL на произвольный момент времени в прошлом. Основан на двух компонентах: base backup (физический снимок кластера) и WAL archive (непрерывная цепочка журнальных сегментов от момента backup до целевого времени).

Как работает

  1. Делается base backup — согласованный снимок всего $PGDATA.
  2. WAL-сегменты непрерывно архивируются (в S3, GCS, на NFS) с момента backup и далее.
  3. При восстановлении PostgreSQL стартует из base backup, затем replay-ит WAL-сегменты до указанного recovery_target_time, LSN, имени restore point или transaction id.
  4. После достижения цели кластер открывается как новая timeline.

Настройка шаг за шагом

1. postgresql.conf — включить архивирование:

# postgresql.conf
archive_mode = on
archive_command = 'aws s3 cp %p s3://my-bucket/wal/%f'
# Или через pgBackRest:
# archive_command = 'pgbackrest --stanza=main archive-push %p'
wal_level = replica   # минимум для архива

2. Снять base backup:

# Встроенный pg_basebackup
pg_basebackup -h localhost -U replicator -D /backup/base \
    -Ft -Xs -P --gzip

# Или pgBackRest (рекомендуется для production):
pgbackrest --stanza=main backup --type=full

3. Восстановление на конкретный момент:

# Остановить кластер, очистить PGDATA, восстановить base backup
rm -rf /var/lib/postgresql/17/main/*
tar xzf /backup/base/base.tar.gz -C /var/lib/postgresql/17/main/

# Создать recovery signal
touch /var/lib/postgresql/17/main/recovery.signal
# postgresql.conf или postgresql.auto.conf:
restore_command = 'aws s3 cp s3://my-bucket/wal/%f %p'
recovery_target_time = '2026-05-18 14:30:00+00'
recovery_target_action = 'promote'   # promote | pause | shutdown

4. Запустить PostgreSQL — он сам replay-ит WAL и откроется.

Мониторинг архива

-- Последний успешно заархивированный WAL:
SELECT last_archived_wal, last_archived_time,
       last_failed_wal, last_failed_time,
       archived_count, failed_count
FROM pg_stat_archiver;

Подводные камни

  • Разрыв в WAL archive (потерянный или повреждённый сегмент) останавливает PITR раньше цели — обнаруживают только при restore drill, не в момент аварии.
  • Слишком короткий retention WAL-сегментов делает старый base backup бесполезным: цепочка обрывается до момента backup.
  • archive_command должен возвращать 0 только при успешной копии; любой non-zero вызывает повтор и задержку переключения WAL — нужен алерт на last_failed_wal.
  • Восстановление на старую timeline без остановки downstream-систем (очереди, реплики) порождает рассинхронизацию и дублирование событий.
  • base backup + весь WAL от момента backup до recovery_target может занимать сотни GB — нужно планировать пропускную способность сети и место на restore-хосте.
  • Без регулярных автоматических restore drill (ежемесячно) нельзя быть уверенным в рабочести PITR — наличие файлов не равно восстанавливаемости.
  • recovery_target_action = 'pause' позволяет проверить данные перед promote, но кластер остаётся read-only; при ошибке нужен restart с другим target.

Common mistakes

  • Хранить base backup без WAL archive.
  • Не проверять restore.
  • Путать logical dump с PITR.

What the interviewer is testing

  • Просит объяснить цепочку base backup + WAL.
  • Проверяет RPO/RTO.
  • Уточняет recovery target и timeline.

Sources

Related topics