Представьте: в пятницу вечером кто-то случайно удалил таблицу с заказами. Или выкатили миграцию, которая затёрла данные. Всё, что стоит между вами и катастрофой — это резервная копия. Разберём, как она устроена в PostgreSQL.
Два подхода: логический и физический backup
В PostgreSQL есть два принципиально разных способа создать резервную копию.
Логический backup — это выгрузка данных в виде SQL-команд или структурированного формата. Инструмент — pg_dump. Вы получаете файл, из которого можно воссоздать конкретную базу, схему или таблицу. Работает медленнее, но гибко: можно взять только нужные таблицы, перенести данные на другую версию PostgreSQL.
Физический backup — это копия файлов на диске, из которых состоит кластер PostgreSQL. Инструмент — pg_basebackup. Быстрее и подходит для продакшена, потому что поддерживает восстановление на точный момент времени (об этом ниже). Минус — версия PostgreSQL при восстановлении должна совпадать.
pg_dump (логический) | pg_basebackup (физический) | |
|---|---|---|
| Что копирует | таблицы, схемы, одну БД | весь кластер |
| Размер | компактнее (без раздутых блоков) | как на диске |
| Скорость создания | медленно | быстро |
| Скорость восстановления | медленно (разбор SQL) | быстро |
| Перенос на другую версию PG | да | нет |
| Восстановление на момент времени | нет | да (с WAL archive) |
| Когда использовать | отладка, миграция, разовые задачи | продакшен, репликация |
Для продакшена обычно настраивают физический backup плюс WAL archive — это даёт возможность восстановиться на любой момент. Логические дампы используют для разработки и отладки.
pg_dump: базовое использование
Простейший вариант — выгрузить базу в SQL-файл:
pg_dump -U user -h host mydb > mydb.sql
psql -U user -h host mydb_new < mydb.sql
Это удобно для небольших баз. Файл читаемый, его можно открыть в текстовом редакторе.
Custom format — рекомендуемый способ
Для серьёзного использования лучше брать custom format (-Fc). Он компактнее и позволяет восстанавливать параллельно:
pg_dump -Fc -U user -h host mydb > mydb.dump
pg_restore -j 4 -d mydb_new mydb.dump # 4 параллельных потока
Флаг -j 4 при восстановлении заметно ускоряет процесс на больших базах — каждый поток обрабатывает свои таблицы.
Полезные флаги
pg_dump --schema=public # только одна схема
pg_dump --table=order_doc # только одна таблица
pg_dump --schema-only # только структура без данных
pg_dump --data-only # только данные без структуры
pg_dump --exclude-table=audit_log # исключить таблицу
pg_dump --no-owner --no-acl # для restore в другой кластер
Роли и глобальные настройки
pg_dump копирует только одну базу. Роли, tablesplace и глобальные настройки хранятся на уровне кластера — их копирует pg_dumpall:
pg_dumpall --globals-only > globals.sql # роли, tablespaces
pg_dump mydb > mydb.sql # данные базы
Восстановить базу локально для отладки
Типичный сценарий: у пользователя воспроизводится баг, нужен дамп продакшен-базы для локальной отладки.
createdb -U postgres customer_debug
pg_restore -d customer_debug -j 4 customer-prod-2026-05-01.dump
psql customer_debug
Важно: дамп продакшена перед передачей нужно анонимизировать — убрать персональные данные. Это требование 152-ФЗ и GDPR. Инструменты для этого — postgresql_anonymizer и ручные UPDATE-скрипты.
Никогда не передавайте необработанный дамп с реальными данными пользователей.
pg_basebackup: физический backup кластера
Физический backup создаёт точную копию файлов кластера:
pg_basebackup -U replicator -h master -D /backup/2026-05-07 -Ft -z -P
-Ft— упаковать в tar.-z— сжать через gzip.-P— показывать прогресс.
Для восстановления нужно распаковать архив в data_directory и запустить PostgreSQL. Версия PostgreSQL при этом должна совпадать с той, с которой делался backup — это ограничение физического подхода.
PITR: восстановление на момент времени
Самая мощная возможность для продакшена — Point-In-Time Recovery. Смысл: взять физический backup и «доиграть» поверх него журнальные файлы WAL до нужного момента.
Если кто-то в 14:30 случайно удалил все заказы, а backup был в 02:00 — PITR позволит восстановиться на 14:29, потеряв всего минуту, а не полдня работы.
Для этого нужно настроить WAL archive на сервере:
archive_mode = on
archive_command = 'rsync %p backup-host:/wal-archive/%f'
Это означает: каждый заполненный WAL-сегмент копируется на отдельный сервер. Так формируется непрерывная цепочка изменений.
Когда нужно восстановиться на конкретный момент:
# recovery.signal в data_directory + postgresql.conf:
restore_command = 'rsync backup-host:/wal-archive/%f %p'
recovery_target_time = '2026-05-07 14:29:00 MSK'
PostgreSQL возьмёт базовый backup, затем применит WAL-файлы один за другим и остановится точно в 14:29. Это операция для DBA — но разработчику важно понимать принцип.
Как долго хранить резервные копии
Типичная схема хранения:
- ежедневные копии — 7 дней;
- еженедельные — 4 недели;
- ежемесячные — 12 месяцев;
- непрерывный WAL archive — последние 7 дней.
Все резервные копии должны лежать отдельно от сервера с данными — на S3, NAS или в облачном хранилище. Копия на той же машине не защищает: если диск умер, умерло всё.
И главное правило: резервная копия, которую не проверяли — это не копия. Регулярно проверяйте, что из неё реально можно восстановиться. Иначе в момент катастрофы окажется, что файл повреждён.
Резервные копии в multi-tenant архитектуре
Когда одна база обслуживает несколько клиентов, стратегия зависит от того, как разделены данные:
- Все клиенты в одних таблицах (
tenant_id-колонка) — backup всей базы, при необходимости фильтруют черезCOPY ... WHERE tenant_id = ?. - Схема на клиента (
schema-per-tenant) —pg_dump --schema=tenant_Xдаёт резервную копию конкретного клиента. - База на клиента (
db-per-tenant) — у каждой базы своё расписание backup.
Что делать, если «всё сломалось»
Алгоритм действий при потере или повреждении данных:
- Остановить изменения — не делать новых INSERT, UPDATE, DELETE. Каждое изменение после катастрофы усложняет восстановление.
- Позвать DBA или владельца инфраструктуры.
- Сделать копию текущего состояния прежде, чем что-то восстанавливать.
- Восстановиться через PITR на момент до проблемы — если настроен WAL archive.
- Если PITR нет — последний хороший backup плюс ручное восстановление потерянных данных.
Важный нюанс: если таблицу удалили в открытой транзакции и она ещё не зафиксирована — проверьте pg_stat_activity. Если транзакция ещё живёт, ROLLBACK вернёт данные без всяких backup.
Частые ошибки
Backup на той же машине. Если сервер выходит из строя, теряются и данные, и резервная копия. Всегда в отдельное хранилище.
Не проверять восстановление. Backup существует только тогда, когда из него реально восстановились. Без регулярной проверки — это просто файл.
Дамп продакшена без анонимизации. Передача данных реальных пользователей нарушает законодательство. Перед любой передачей — убирать персональные данные.
--inserts для больших таблиц. Режим --inserts генерирует по одному INSERT на строку — это в десятки раз медленнее стандартного режима с COPY. Использовать только когда это действительно нужно (например, совместимость с другими СУБД).
Восстановление физического backup в другую мажорную версию PostgreSQL. Это не работает. Для переноса между версиями — только pg_dump (логический).
Коротко
- Два вида backup: логический (
pg_dump) — гибко, для отладки; физический (pg_basebackup) — быстро, для продакшена. pg_dump -Fcдаёт компактный файл;pg_restore -j 4восстанавливает параллельно.- Физический backup + WAL archive = PITR — восстановление на любой момент прошлого.
pg_dumpall --globals-onlyкопирует роли и глобальные настройки кластера.- Backup обязательно в отдельном хранилище — локальный backup не защищает.
- Backup без проверки восстановления — не backup.
- Дамп продакшена перед передачей анонимизировать.
Что почитать дальше
- WAL в PostgreSQL — как устроен журнал и зачем он нужен для PITR.
- Репликация в PostgreSQL —
pg_basebackupиспользуется и для создания реплик. - Multi-tenancy в PostgreSQL — стратегии разделения данных по клиентам.