← назад к разделу

Представьте: в пятницу вечером кто-то случайно удалил таблицу с заказами. Или выкатили миграцию, которая затёрла данные. Всё, что стоит между вами и катастрофой — это резервная копия. Разберём, как она устроена в 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.

Что делать, если «всё сломалось»

Алгоритм действий при потере или повреждении данных:

  1. Остановить изменения — не делать новых INSERT, UPDATE, DELETE. Каждое изменение после катастрофы усложняет восстановление.
  2. Позвать DBA или владельца инфраструктуры.
  3. Сделать копию текущего состояния прежде, чем что-то восстанавливать.
  4. Восстановиться через PITR на момент до проблемы — если настроен WAL archive.
  5. Если 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 — стратегии разделения данных по клиентам.