Автоматические бэкапы PostgreSQL: настройка на живом сервере
Настроим ежедневную резервную копию базы PostgreSQL 16 через pg_dump и systemd timer: файл не появится в каталоге, пока выгрузка не завершится. Разберём, чем такой вариант отличается от физического бэкапа и как проверить восстановление.

Настроим ежедневный бэкап базы PostgreSQL 16 на Linux-сервере: systemd запустит выгрузку по расписанию, а незавершённый файл не будет выглядеть как готовая копия. Пример подходит для одной базы и не заменяет копию на другом сервере: если диск выйдет из строя, локальный каталог бэкапов пропадёт вместе с ним.
Что именно будем сохранять
Возьмём базу с именем appdb, локальный PostgreSQL и systemd. Для выгрузки используем pg_dump из PostgreSQL 16, а расписание зададим таймером systemd. Команды запускайте от имени администратора сервера; служба бэкапа должна иметь права читать базу и писать в каталог копий.
До начала подготовьте:
- PostgreSQL 16 и клиентскую утилиту
pg_dumpверсии 16; - Linux-сервер с systemd;
- неинтерактивную аутентификацию для пользователя службы: настройте её штатным для вашего сервера способом и проверьте подключение до автоматизации;
- каталог на диске с запасом места. Размер будущего архива заранее не угадывайте — сначала измерьте пробный файл.
В примере предполагается, что процесс может подключиться к локальной базе без запроса пароля. Если на сервере это не так, настройте безопасную аутентификацию отдельно. Не вписывайте пароль прямо в скрипт или unit-файл.
Три подхода: выбираем цену и охват
pg_dump создаёт логическую копию одной базы. Это удобно для небольшой и средней базы, выборочного восстановления и переноса между серверами. Но выгрузка и обратная загрузка могут занять заметное время на крупных объёмах, а роли и другие общие объекты кластера в такой файл не входят.
| Подход | Что сохраняет | Цена решения |
|---|---|---|
pg_dump | Одну базу в логическом формате | Просто проверить и восстановить отдельно; время восстановления растёт вместе с объёмом данных |
pg_basebackup | Физическую копию кластера PostgreSQL | Подходит для восстановления кластера, но требует продумать место хранения, WAL и процедуру восстановления |
| Снимок диска или файловой системы | Состояние тома или диска | Может быть быстрым, но для базы важна согласованность снимка; одного снимка недостаточно без проверки восстановления |
Для примера выбираем pg_dump: цель — регулярно сохранять одну базу, а не строить систему восстановления кластера до конкретной секунды. Если вам нужно восстановить состояние между двумя ежедневными запусками, изучите архивирование WAL и восстановление на момент времени отдельно.
Расписание делает копию регулярной, но не доказывает, что из неё можно восстановиться. Доказательство — успешное тестовое восстановление.
Настраиваем выгрузку
Создайте каталог для файлов и скрипт /usr/local/sbin/pg-backup.sh. Назначьте каталогу и скрипту владельца, от имени которого будет работать служба; не делайте каталог доступным на запись всем пользователям. В примере служба называется backup, а каталог — /var/backups/postgresql.
#!/bin/sh
set -eu
umask 077
BACKUP_DIR=/var/backups/postgresql
DATABASE=appdb
STAMP=$(date -u +%Y%m%dT%H%M%SZ)-$$
FINAL="$BACKUP_DIR/$DATABASE-$STAMP.dump"
TMP=$(mktemp "$BACKUP_DIR/.$DATABASE-$STAMP.XXXXXX")
trap 'rm -f "$TMP"' EXIT
pg_dump --format=custom --no-owner --file="$TMP" "$DATABASE"
test -s "$TMP"
mv "$TMP" "$FINAL"
Здесь custom — архивный формат PostgreSQL, который можно просматривать и восстанавливать утилитой pg_restore. Временный файл создаётся в том же каталоге, что и итоговый: если выгрузка завершится ошибкой, готовое имя не появится. Метка времени задана в UTC, а $$ помогает не столкнуть имена при ручных запусках.
Сохраните скрипт с правом запуска. До настройки расписания запустите его от имени будущего пользователя службы. Проверка: команда завершилась с кодом 0, в каталоге появился файл appdb-....dump, а его размер больше нуля. Если подключение требует пароль и команда ждёт ввода, автоматический запуск пока не настроен.
Добавляем расписание systemd
Создайте unit-файл /etc/systemd/system/pg-backup.service. Пользователь и группа должны совпадать с учётной записью, которой доступны база и каталог.
[Unit]
Description=Backup PostgreSQL appdb
[Service]
Type=oneshot
User=backup
Group=backup
ExecStart=/usr/local/sbin/pg-backup.sh
Теперь создайте /etc/systemd/system/pg-backup.timer. Время указано по локальному часовому поясу сервера; перед включением проверьте его настройки.
[Unit]
Description=Daily PostgreSQL backup schedule
[Timer]
OnCalendar=*-*-* 03:15:00
Persistent=true
RandomizedDelaySec=10m
[Install]
WantedBy=timers.target
Перечитайте unit-файлы и включите таймер:
sudo systemctl daemon-reload
sudo systemctl enable --now pg-backup.timer
sudo systemctl list-timers pg-backup.timer
В выводе list-timers проверьте время следующего запуска. Чтобы не ждать ночи, запустите службу вручную и проверьте её состояние и журнал:
sudo systemctl start pg-backup.service
sudo systemctl status pg-backup.service
sudo journalctl -u pg-backup.service
Успех — служба завершилась без ошибки, журнал не содержит сообщения об отказе, а новый архив появился в каталоге. Таймер запускает ту же службу по расписанию; успешный ручной запуск проверяет скрипт и доступы, но не весь будущий цикл наблюдения.
Проверяем не только создание файла
Сначала убедитесь, что архив читается:
pg_restore --list /var/backups/postgresql/ИМЯ_АРХИВА.dump
Замените ИМЯ_АРХИВА.dump на существующий файл. Если команда показывает список объектов, архив распознаётся. Это ещё не восстановление: ошибки прав, версии или нехватки места могут проявиться только при загрузке данных.
Периодически восстанавливайте копию в отдельную тестовую базу. Для архива PostgreSQL 16 пример выглядит так:
createdb restore_check
pg_restore --exit-on-error --dbname=restore_check /var/backups/postgresql/ИМЯ_АРХИВА.dump
Проводите тест на подходящем стенде или в согласованное окно: восстановление расходует диск и ресурсы, а имя тестовой базы должно быть свободно. После проверки оцените, открываются ли нужные таблицы и совпадает ли ожидаемое содержимое. Зафиксируйте, сколько заняли создание архива и восстановление: эти времена покажут, укладывается ли процедура в допустимое окно простоя.
Ежедневная выгрузка хранится на том же сервере и сама по себе не защищает от поломки диска, удаления каталога или компрометации хоста. Следующий шаг — организовать отдельное место хранения, ограничить к нему доступ, определить срок хранения копий и регулярно проверять восстановление. Автоматическое удаление старых файлов добавляйте только после того, как проверили новую копию и правила хранения: иначе ошибка расписания может удалить последние рабочие архивы.
Термин: WAL (журнал предзаписи) — записи об изменениях в PostgreSQL. Архивирование WAL вместе с базовой копией позволяет настраивать восстановление к выбранному моменту времени; это отдельная задача, которой ежедневный pg_dump не решает.
Тест и проверочная: Быстрые ответы с объяснением, почему остальные варианты неверны
Спросить за 10 ₽Источники: PostgreSQL 16: pg_dump, systemd.timer — таймерные unit-файлы
Частые вопросы
Можно ли использовать этот пример с PostgreSQL 15 или 17?
Скрипт не запускается без ввода пароля. Что делать?
Если ежедневный запуск пропустился, копия появится позже?
Достаточно ли проверить, что файл ненулевого размера?
Можно ли хранить копии только на сервере с базой?
Почему в архиве нет пользователей и других баз кластера?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.