Top.Mail.Ru
OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

PITR для PostgreSQL: архивация WAL, base backup и тест восстановления

Практическое руководство для админов и DevOps: как включить архивацию WAL в PostgreSQL, корректно снимать base backup, удерживать нужное окно журналов и регулярно проверять восстановление до точки во времени. Разбираем конфигурацию, автоматизацию, типичные ошибки и сценарий полноценного теста.
PITR для PostgreSQL: архивация WAL, base backup и тест восстановления

PITR (Point-In-Time Recovery) — это возможность восстановить физический кластер PostgreSQL до состояния на конкретный момент времени. В реальной эксплуатации PITR защищает от человеческих ошибок, неудачных миграций и некорректных изменений данных, дополняя регулярные «полные» бэкапы. В статье разберём, как включить архивацию WAL, корректно снимать base backup, выстроить политику хранения и отработать тест восстановления.

Как работает PITR вкратце

PostgreSQL записывает все изменения в журналы предзаписи WAL (Write-Ahead Log). Если у нас есть:

  • актуальный «срез» кластера — base backup;
  • непрерывная последовательность WAL-сегментов с момента снятия этого среза;

— то мы можем «прокрутить» состояние данных до выбранной точки: по времени, по метке восстановления или по конкретному LSN.

PITR — физическое восстановление всего кластера: вы получаете консистентное состояние всех БД кластера. Логические бэкапы (дампы) — отдельная тема.

Подготовка: требования и план

Перед стартом определите RPO/RTO. RPO (сколько данных допустимо потерять) определяет частоту base backup и размер окна хранения WAL. RTO задаёт сценарий и скорость восстановления (куда, как быстро, чем автоматизировать).

Минимум потребуется:

  • Дисковое пространство под архив WAL и несколько поколений «полных» бэкапов.
  • Синхронизированное время (NTP), чтобы точно указывать recovery_target_time и сопоставлять события.
  • Выделенная директория для архива WAL (локально или во внешнем хранилище) и права пользователя postgres.
  • Понимание версии PostgreSQL (для 12+ используется файл-сигнал recovery.signal, а не recovery.conf).

Тестовое восстановление безопаснее выполнять на отдельном стенде. Удобно поднять его на VDS, чтобы не рисковать продуктивом.

pg_basebackup и папка архива WAL на сервере Linux

Включаем архивацию WAL

Необходимо непрерывно сохранять все завершённые WAL-сегменты в отдельное устойчивое хранилище. Управляют этим параметры archive_mode и archive_command.

Создаём директорию для архива

sudo mkdir -p /var/lib/postgresql/wal_archive
sudo chown -R postgres:postgres /var/lib/postgresql/wal_archive
sudo chmod 700 /var/lib/postgresql/wal_archive

Правим конфигурацию PostgreSQL

Откройте postgresql.conf и проверьте/добавьте ключевые параметры:

wal_level = replica
archive_mode = on
archive_command = 'test ! -f /var/lib/postgresql/wal_archive/%f && cp %p /var/lib/postgresql/wal_archive/%f'
archive_timeout = 60s
logging_collector = on
log_checkpoints = on
log_connections = on
log_destination = 'stderr'

Пояснения:

  • wal_level = replica — минимально необходимый уровень для PITR.
  • archive_mode = on — включает архивацию завершённых WAL-сегментов.
  • archive_command — должен быть идемпотентным. В примере мы не перезаписываем уже сохранённые файлы. Команда обязана возвращать 0 при успехе, иначе PostgreSQL будет повторять попытки.
  • archive_timeout — принудительно «закрывает» сегмент WAL, если он долго не заполняется (актуально при низкой нагрузке).

Примените конфигурацию перезапуском:

sudo systemctl restart postgresql

Проверяем, что сегменты уходят в архив

sudo -u postgres psql -c "SELECT * FROM pg_stat_archiver;"

Следите за полями archived_count и last_archived_wal. Убедитесь, что в директории архива появляются файлы вида 0000000100000000000000A1.

Снимаем base backup

Base backup — консистентная копия каталога данных. Обычно его снимают утилитой pg_basebackup. Для сетевого бэкапа потребуется роль с правами репликации.

Создаём роль для бэкапов (опционально)

sudo -u postgres psql -c "CREATE ROLE bkp REPLICATION LOGIN PASSWORD 'strongpass';"

Если бэкап запускается локально от пользователя postgres, дополнительная роль не обязательна.

Вариант: tar-архивы

sudo -u postgres pg_basebackup -D /backups/pg/base/2025-01-15 -F tar -X stream -c fast -z -P
  • -F tar — формат tar (удобно хранить и переносить).
  • -X stream — включить WAL в поток бэкапа, гарантируя консистентность без отдельного копирования текущих WAL.
  • -c fast — быстрый checkpoint перед началом копии.
  • -z — сжатие tar.
  • -P — прогресс.

Вариант: «плоская» директория

sudo -u postgres pg_basebackup -D /backups/pg/base/2025-01-15 -F p -X stream -c fast -P

Этот формат удобен для локального восстановления, так как не требует распаковки tar.

Проверка целостности бэкапа

Проверьте, что бэкап содержит файл backup_manifest (в новых версиях) и каталоги/файлы системных баз (base, global, pg_wal и т. д.). Для tar — убедитесь, что архив читается без ошибок:

sudo -u postgres tar -tf /backups/pg/base/2025-01-15/base.tar.gz | head -n 20

Политика хранения: сколько держать WAL и бэкапов

Чтобы восстановиться в любую точку между двумя base backup, нужно хранить все WAL за этот период. Типичный подход:

  • Полный бэкап раз в сутки (или чаще для более строгого RPO).
  • Хранить N полных бэкапов (например, 7–14 дней — зависит от объёма и требований).
  • Хранить все WAL-сегменты, начиная с самого старого из сохранённых бэкапов.

Ротация выполняется внешними скриптами/утилитами: удаляем старые base backup и соответствующие им WAL. Нельзя удалять WAL, которые ещё нужны для любого из оставшихся бэкапов. Удобно хранить для каждого бэкапа метку с минимальным требуемым сегментом или LSN.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Практический тест восстановления до точки (PITR)

Регулярный тест — единственный надёжный способ убедиться, что PITR работает и соответствует RPO/RTO. Ниже — воспроизводимый сценарий для PostgreSQL 12+.

1) Создаём метку восстановления

Перед потенциально опасными изменениями создайте явную метку восстановления:

sudo -u postgres psql -d postgres -c "SELECT pg_create_restore_point('before_migration');"

Запомните метку и время. Для контроля можно посмотреть текущий LSN:

sudo -u postgres psql -d postgres -c "SELECT pg_current_wal_lsn();"

2) Имитируем изменения

sudo -u postgres psql -d postgres -c "CREATE TABLE pitr_demo(id int primary key, note text);"
sudo -u postgres psql -d postgres -c "INSERT INTO pitr_demo VALUES (1, 'bad change');"

Считайте это ошибочным изменением, от которого мы захотим уйти при восстановлении.

3) Готовим чистое место восстановления

Остановите кластер и подготовьте каталог данных для восстановления (используем отдельную директорию, чтобы не рисковать продуктивом):

sudo systemctl stop postgresql
sudo mkdir -p /var/lib/postgresql/restore_datadir
sudo chown -R postgres:postgres /var/lib/postgresql/restore_datadir
sudo chmod 700 /var/lib/postgresql/restore_datadir

4) Разворачиваем base backup

Если бэкап в tar:

sudo -u postgres tar -xzf /backups/pg/base/2025-01-15/base.tar.gz -C /var/lib/postgresql/restore_datadir

Если бэкап снят в «плоский» каталог — скопируйте содержимое внутрь /var/lib/postgresql/restore_datadir с сохранением прав.

5) Настраиваем восстановление

Добавьте в postgresql.conf (внутри каталога восстановления) параметры восстановления:

restore_command = 'cp /var/lib/postgresql/wal_archive/%f %p'
recovery_target_name = 'before_migration'
recovery_target_action = 'promote'
recovery_target_timeline = 'latest'

Создайте файл-сигнал восстановления:

sudo -u postgres touch /var/lib/postgresql/restore_datadir/recovery.signal

Если в архиве WAL используется сжатие, укажите соответствующую команду, например для gzip:

restore_command = 'gzip -dc /var/lib/postgresql/wal_archive/%f > %p'

6) Стартуем восстановление

Запускаем кластер, указав на новый каталог данных. В зависимости от пакета сервиса может понадобиться отдельный юнит или временная подмена PGDATA. Для демонстрации используем pg_ctl:

sudo -u postgres pg_ctl -D /var/lib/postgresql/restore_datadir -l /var/lib/postgresql/restore_datadir/logfile start

PostgreSQL начнёт применять WAL из архива. Когда будет достигнута метка before_migration, произойдёт автоматический promote благодаря recovery_target_action = 'promote'.

7) Проверяем результат

sudo -u postgres psql -d postgres -c "SELECT pg_is_in_recovery();"
sudo -u postgres psql -d postgres -c "\\dt"
sudo -u postgres psql -d postgres -c "SELECT * FROM pitr_demo;"

Если восстановление корректно сработало к метке до внесения «плохих» изменений, таблица/строки, созданные после метки, отсутствуют. Также проверьте таймлайн:

sudo -u postgres psql -d postgres -c "SELECT timeline_id FROM pg_control_checkpoint();"

Мониторинг и диагностика

Полезные источники:

  • pg_stat_archiver — статус архивации WAL.
  • Логи PostgreSQL — сообщения о неудачных попытках archive_command/restore_command.
  • pg_waldump — просмотр содержимого WAL для расследования.
sudo -u postgres pg_waldump /var/lib/postgresql/wal_archive/0000000100000000000000A1 | head -n 20

Типичные ошибки и как их избежать

  • Неидемпотентный archive_command. При повторных вызовах можно перезаписать или повредить целевой файл. Всегда проверяйте существование файла и код возврата.
  • Недостаточная ротация. Диск под архивом заполняется внезапно. Введите политику хранения и мониторинг свободного места.
  • Преждевременное удаление WAL. Нельзя удалять WAL до того, как он перестанет быть нужен самому старому сохранённому base backup.
  • Несовместимость версий при восстановлении. Нельзя восстанавливать данные, снятые на одной мажорной версии, в другую. Используйте ту же мажорную версию PostgreSQL.
  • Права и безопасность. Директории бэкапов и архива должны принадлежать postgres и быть закрыты от чтения посторонними. При необходимости используйте шифрование хранения.
  • Ожидания от archive_timeout. На низкой нагрузке без archive_timeout WAL может долго не «закрываться» — точки восстановления размываются.

Автоматизация: расписания и очистка

Минимальная автоматизация: периодический base backup и ротация старых бэкапов/журналов. Примеры cron:

# Ежедневный base backup (tar + gzip)
0 2 * * * postgres pg_basebackup -D /backups/pg/base/$(date +\%F) -F tar -X stream -c fast -z -P

# Очистка бэкапов старше 14 дней
30 3 * * * root find /backups/pg/base -maxdepth 1 -type d -mtime +14 -exec rm -rf {} \;

# Очистка WAL старше 14 дней (настраивайте под свою политику)
0 4 * * * root find /var/lib/postgresql/wal_archive -type f -mtime +14 -delete

Прежде чем удалять WAL, убедитесь, что не затронете диапазон, необходимый для самого старого оставшегося бэкапа. Полезно хранить файл-«маяк» с указанием минимального нужного сегмента для каждого бэкапа.

Продвинутые опции

  • Сжатие и шифрование WAL. Вместо простого cp используйте потоковое сжатие (gzip, lz4, zstd) и при необходимости шифрование. Согласуйте это с restore_command.
  • Альтернативные инструменты. Специализированные утилиты для архивации WAL и управления репозиторием дают дедупликацию, параллелизм и удобную политику хранения.
  • pg_receivewal. Для непрерывного приёма WAL по сети можно использовать потоковый приёмник — иногда удобнее, чем archive_command.
  • Оффсайт-копии. Храните как минимум одну копию бэкапов и WAL вне основного узла/ДЦ. См. практику резервного копирования в объектное хранилище в материале «Restic и Borg для S3-совместимых бэкапов» по ссылке резервное копирование в объектное хранилище.

Восстановление PostgreSQL из base backup с параметрами recovery и применением WAL

Контрольный чек‑лист PITR

  • Включены wal_level = replica, archive_mode = on, настроен безопасный archive_command.
  • Архив WAL стабильно пополняется, pg_stat_archiver без ошибок.
  • Есть свежий base backup, проверенный на целостность.
  • Определена и реализована политика хранения: base backup + все WAL между ними.
  • Регулярно проводится тест восстановления на стенде: восстановление до метки/времени работает.
  • Описана процедура «поднять из бэкапа» с проверками и таймингами (RTO).

Итоги

PITR в PostgreSQL — это не только настройка пары параметров, но и дисциплина: непрерывная архивация WAL, предсказуемые полные бэкапы, прозрачная ротация и периодические тесты восстановления. Следуя шагам из руководства, вы получите воспроизводимую схему с понятными RPO/RTO и уверенность, что в критический момент база будет восстановлена до нужной точки.

Поделиться статьей

Вам будет интересно

PHP-настройки на виртуальном хостинге: .user.ini, php_value и безопасные лимиты OpenAI Статья написана AI Fastfox

PHP-настройки на виртуальном хостинге: .user.ini, php_value и безопасные лимиты

Как на виртуальном хостинге корректно повысить memory_limit, upload_max_filesize и другие директивы PHP? Что выбрать — .user.ini и ...
Точечное восстановление MySQL/MariaDB: binlog, GTID и контроль точек OpenAI Статья написана AI Fastfox

Точечное восстановление MySQL/MariaDB: binlog, GTID и контроль точек

Точечное восстановление (PITR) спасает от случайных DROP/UPDATE и багов релизов. Разберём, как подготовить MySQL/MariaDB для безоп ...
Blackbox‑мониторинг сайтов: проверки HTTP/TCP/ICMP и алерты в Prometheus OpenAI Статья написана AI Fastfox

Blackbox‑мониторинг сайтов: проверки HTTP/TCP/ICMP и алерты в Prometheus

Практическое руководство для админов и DevOps: добавляем blackbox‑мониторинг сайтов и портов с Prometheus и Blackbox Exporter. HTT ...