Бэкапы PostgreSQL через pgBackRest: с нуля до восстановления
Долго жил с pg_dump по крону и считал, что бэкапы у меня есть. Ровно до момента, когда понадобилось
восстановить базу на состояние «час назад», а не «прошлая ночь». Дамп так не умеет, нужен архив WAL.
Перебрал варианты и остановился на pgBackRest: он один пакет, понятно настраивается и умеет проверять сам себя.
Что получилось в итоге
- полный бэкап раз в неделю, дифференциальный каждую ночь;
- непрерывный архив WAL, то есть восстановление на любой момент;
- репозиторий на отдельном диске плюс копия на внешний сервер;
- ежемесячная проверка: восстановление на тестовую машину по расписанию.
Конфигурация
Весь конфиг помещается в один файл /etc/pgbackrest/pgbackrest.conf:
[global]
repo1-path=/backup/pgbackrest
repo1-retention-full=4
repo1-retention-diff=7
compress-type=zst
process-max=2
start-fast=y
[main]
pg1-path=/var/lib/postgresql/16/main
В postgresql.conf включаем архивирование:
archive_mode = on
archive_command = 'pgbackrest --stanza=main archive-push %p'
wal_level = replica
После перезапуска PostgreSQL создаём stanza и сразу проверяем, что архив доходит до репозитория:
sudo -u postgres pgbackrest --stanza=main stanza-create
sudo -u postgres pgbackrest --stanza=main check
Если check висит больше минуты, почти наверняка не работает archive_command.
Смотрите лог PostgreSQL, а не pgBackRest: ошибка будет там.
Расписание
Я использую systemd timers (почему, писал отдельно), но с cron тоже всё просто:
30 2 * * 0 postgres pgbackrest --stanza=main --type=full backup
30 2 * * 1-6 postgres pgbackrest --stanza=main --type=diff backup
Восстановление — то, ради чего всё затевалось
Бэкап, из которого ни разу не восстанавливались, это надежда, а не бэкап. Восстановление на момент времени:
systemctl stop postgresql
sudo -u postgres pgbackrest --stanza=main --delta \
--type=time "--target=2025-03-14 11:20:00+03" restore
systemctl start postgresql
--delta экономит время: pgBackRest сравнивает файлы по контрольным суммам и перезаписывает
только изменившиеся. На базе в 40 ГБ это разница между сорока минутами и пятью.
Чего я не ожидал
- Место под WAL. При массовой загрузке данных архив растёт быстрее самой базы. Мониторьте диск репозитория.
- Часовой пояс в target. Указывайте его явно, иначе восстановитесь не туда.
- Права. Каталог репозитория должен принадлежать
postgres, иначе ошибка будет невнятной.
Через полгода эксплуатации: два реальных восстановления, оба прошли спокойно. Ради этого стоило потратить вечер.