Как настроить создание резервных копий для PostgreSQL, используя внутренние механизмы?

«Как настроить создание резервных копий для PostgreSQL, используя внутренние механизмы?» — вопрос из категории Базы данных, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В продакшн-среде с PostgreSQL я настраиваю отказоустойчивую стратегию бэкапов, основанную на комбинации логических дампов и непрерывного архивирования WAL (Write-Ahead Log). Это позволяет восстановить базу на любой момент времени (Point-in-Time Recovery - PITR).

1. Базовая настройка в postgresql.conf:

# Уровень детализации WAL должен быть как минимум 'replica' для архивации
wal_level = replica

# Включаем режим архивации
archive_mode = on

# Команда, которая будет выполняться для архивации сегмента WAL.
# Важно, чтобы команда возвращала 0 только в случае успеха.
archive_command = 'test ! -f /mnt/backup/wal_archive/%f && cp %p /mnt/backup/wal_archive/%f'
# Пример с использованием утилиты pg_archivecleanup для ротации:
# archive_command = 'pg_archivecleanup /mnt/backup/wal_archive %r 2>/dev/null || true && cp %p /mnt/backup/wal_archive/%f'

# Рекомендуется для ускорения PITR
full_page_writes = on

После изменения конфигурации требуется перезагрузка сервиса PostgreSQL.

2. Создание базовых (полных) бэкапов: Я использую pg_basebackup для создания физической копии кластера. Это быстрее, чем логический дамп, и является основой для PITR.

# Пример создания базового бэкапа с использованием слотов репликации для контроля задержки
pg_basebackup -D /mnt/backup/base_backup_$(date +%Y%m%d) 
  -U replicator -v -P 
  --wal-method=stream 
  --write-recovery-conf 
  --slot=backup_slot

Эту операцию можно выполнять регулярно (например, раз в неделю) без остановки основной БД.

3. Автоматизация и мониторинг: Я создаю скрипт для бэкапа и настраиваю его выполнение через cron или системный таймер. Критически важно регулярно тестировать восстановление.

#!/bin/bash
# Скрипт /usr/local/bin/pg_backup.sh
BACKUP_DIR="/mnt/backup"
DATE=$(date +%Y%m%d_%H%M%S)

# 1. Создаём базовый бэкап
pg_basebackup -D $BACKUP_DIR/base_$DATE -U backup_user -v -P --wal-method=stream

# 2. Принудительно создаём контрольную точку и архивируем текущий WAL
psql -U backup_user -d postgres -c "SELECT pg_switch_wal();"

# 3. Очищаем старые бэкапы (храним 7 последних базовых копий)
find $BACKUP_DIR/base_* -maxdepth 0 -type d -mtime +7 -exec rm -rf {} ;

# 4. Проверяем целостность архива WAL (упрощённо)
if [ -z "$(ls -A $BACKUP_DIR/wal_archive/)" ]; then
  echo "WARNING: WAL archive directory is empty!" | mail -s "PostgreSQL Backup Alert" admin@example.com
fi

4. Восстановление до точки во времени: Для восстановления копируем базовый бэкап в PGDATA, создаём файл recovery.signal и настраиваем postgresql.conf для восстановления из архива WAL до нужного времени.

# В postgresql.conf восстанавливаемой инстанции
restore_command = 'cp /mnt/backup/wal_archive/%f %p'
recovery_target_time = '2023-10-26 15:30:00 UTC'

Такой подход, развёрнутый с помощью конфигурационного менеджмента (Ansible), обеспечивает надёжное восстановление данных.