Копирование и восстановление PostgreSQL
Резервная копия полезна тогда, когда из неё можно получить понятное состояние в другой базе. Наличие файла с расширением dump ещё не показывает, что восстановятся ограничения, связи и нужные прикладные данные. В этом уроке подготовим логическую копию каталога и отдельный маршрут восстановления, сохраняя исходную лабораторию.
Используем PostgreSQL и клиентские утилиты версии 17.11. В архиве продолжения лежит самостоятельная папка catalog-db-advanced/lesson-30: reset, запросы сверки и текст будущих команд. Дамп не создавался, pg_dump и pg_restore не запускались. Мы описываем ожидаемый состав копии по шести курсам и двенадцати урокам, а не сообщаем о выполненном восстановлении ProfessorWeb.
Источник и отдельная цель
Источником служит изолированная professorweb_lab. Для восстановления владелец локальной лаборатории заранее создаёт другую пустую базу professorweb_restore_lab, принадлежащую учебному student. Наши команды не содержат CREATE DATABASE и не требуют выдавать обычному приложению CREATEDB. Адрес, порт и обе базы нужно прочитать до выполнения команды: правильное имя на чужом сервере не гарантирует изоляцию.
Новая цель должна быть пустой, потому что восстановление включает создание схемы и таблиц. Если в цели уже существует catalog, попытка создать объекты будет конфликтовать. Это повод выяснить состояние цели, а не добавить случайно destructive-флаг к источнику. В подготовленном маршруте нет --clean: существующие объекты не удаляются для того, чтобы команда выглядела успешной.
Отдельная цель также позволяет сравнить два каталога. Пока её данные рассматриваются вручную, исходная учебная база продолжает существовать. Прикладное переключение подключения, возвращение пользователей и публикация сайта относятся к другому действию. Восстановить лабораторную копию и заменить production-подключение — разные решения с разными последствиями.
Логический архив
Подготовленная команда сохраняет custom archive:
pg_dump -h 127.0.0.1 -p 5432 -U professorweb_student \
-d professorweb_lab -Fc --no-owner --no-acl \
-f professorweb-lab.dump
Это текст команды для будущего ручного опыта, а не уже полученный файл. Параметр -Fc выбирает формат, который читает pg_restore. Явные источник и имя файла помогают отличить соединение с базой от пути локального артефакта. Пароль не пишется в урок, команду или архив примеров.
pg_dump получает согласованное представление одной базы для логического копирования. Возможность параллельной работы других клиентов не означает, что архив содержит все будущие изменения: копия относится к своему снимку. Поэтому время создания и граница актуальности становятся частью записи о резервной копии. Основные свойства инструмента описаны в официальном руководстве pg_dump.
Наш набор не содержит внешних файлов сайта. Markdown, изображения, настройки веб-сервера, DNS и секреты подключения не превращаются в часть дампа лишь потому, что связаны с каталогом. Для реального ProfessorWeb нужен согласованный план резервирования репозитория и медиа рядом с базой. В текущем учебном каталоге копируется предметный SQL-набор, и это ограничение сформулировано до обсуждения успешного восстановления.
Выбранные no-owner и no-acl упрощают перенос в личную лабораторию, где объекты принадлежат другой роли. Такой архив не следует выдавать за точную копию административного окружения. Кластерные роли, исходные grants и настройки экземпляра требуют отдельного рассмотрения. В custom archive решение не переносить владельцев применяется на стороне pg_restore, поэтому no-owner явно указан и в команде восстановления. После восстановления право чтения приложения не появляется автоматически из названия таблицы.
Чтение состава и восстановление
Перед будущим восстановлением можно рассмотреть список объектов custom archive:
pg_restore --list professorweb-lab.dump
Список помогает увидеть, что архив относится к ожидаемой схеме и включает данные, но не заменяет чтение и проверку происхождения самого архива. В нашем репозитории дампа нет, поэтому мы не показываем выдуманные номера записей или размер файла. Это подготовленная возможность следующего ручного шага.
Команда восстановления направлена только в другую пустую базу:
pg_restore -h 127.0.0.1 -p 5432 -U professorweb_student \
--dbname professorweb_restore_lab \
--no-owner --no-acl --exit-on-error --single-transaction \
professorweb-lab.dump
Здесь --single-transaction связывает выбранное восстановление в одну транзакцию; ошибки не должны оставлять намеренно принятый частичный результат. Для этого небольшого архива не выбирается параллельное восстановление. Возможности и ограничения параметров изложены в pg_restore. Если инструмент сообщает ошибку, нельзя считать цель готовой только потому, что она содержит некоторые таблицы.
Утилиты зафиксированы той же основной версии, что и сервер примера. Совместимость переноса между версиями рассматривают отдельно; не нужно предполагать, что любой старый клиент способен читать новый архив. В редакционной записи должны остаться версии инструментов, выбранная цель и факт завершения будущей операции, когда она действительно будет выполнена.
Сверка данных
В источнике подготовлен lesson.sql, в цели — restore-check.sql с другим guard. Они не меняют каталог. Начальная сверка сравнивает количества и предметные суммы:
SELECT count(*) AS courses, sum(planned_lessons) AS planned
FROM catalog.courses;
SELECT count(*) AS lessons, sum(reading_minutes) AS minutes
FROM catalog.lessons;
Ожидаются шесть курсов с планом 86 и двенадцать фактических уроков с длительностью 127 минут. Число 86 не является количеством восстановленных строк lessons. Публичный план равен 74, потому что курс производительности с планом 12 остаётся черновиком. Это проверка смысла полей, а не только одинаковой длины двух таблиц.
Далее прочитайте id, slug, status и версии карточек. Сохранённые идентификаторы должны продолжать связывать уроки с теми же курсами. Проверяется также отсутствующий body второго урока чернового курса: SQL NULL не должен незаметно превратиться в строку «NULL» или потерянную запись. Совпадение общего COUNT само по себе такого различия не обнаруживает.
Определения ограничений читаются через pg_constraint. Нас интересуют внешние ключи, уникальность позиции урока внутри курса, допустимые статусы и согласование published_at. Данные без этих правил могут выглядеть одинаково сегодня, но завтра принять недопустимую правку. У архивного восстановления задача шире, чем экспорт плоских строк.
Имена объектов и прикладная готовность
После восстановления одинаковые названия таблиц ещё не доказывают одинаковое поведение приложения. Представим, что courses содержит шесть строк, но счётчик identity не согласован с восстановленными ключами. Следующая вставка может обнаружить конфликт, который обычный COUNT не показал. Поэтому полный состав архивного восстановления рассматривается вместе с ограничениями и обслуживающими объектами, а не только с выгруженными значениями CSV.
В нашей подготовленной сверке нет пробной вставки или исполнения клиентского сценария: это ограничение текущей локальной работы. Когда владелец решит провести настоящий опыт, подтверждение работы приложения будет отдельным шагом после чтения предметных данных. Такой шаг записывается как реально выполненный, со своим результатом, а не заранее объявляется успешным в учебном тексте.
Также стоит различить идентичность публичных адресов и место размещения базы. Перенос копии в другую лабораторию не должен менять slug в каждой карточке лишь из-за нового имени подключения. Прикладной маршрут продолжает строиться по сохранённому договору. Так резервное восстановление можно оценивать без случайного переименования материалов и без смешивания технической цели с адресами читательских страниц.
Граница готовности копии
Если завтра каталог будет активно изменяться, дамп не обеспечит сам по себе восстановление до произвольной секунды перед происшествием. Для такой задачи рассматривают физические резервные копии и журналирование отдельно. Этот урок не заявляет настроенную цепочку PITR и не обещает нулевую потерю изменений.
Результат будущей ручной работы стоит записать через наблюдаемые факты: какая копия читалась, в какую пустую базу она восстановлена, какие предметные значения совпали и что намеренно не переносилось. Внешний вид файлов и отсутствие ошибки в одной консоли недостаточны для уверенности в новом подключении приложения.
Наш учебный маршрут заканчивается самостоятельной восстановленной лабораторией, когда владелец выполнит и оценит подготовленные действия. До этого у нас есть воспроизводимый текст процесса и ожидаемые значения. Такая граница позволяет обсуждать резервирование честно и улучшать его по результатам настоящего восстановления, сохраняя исходный каталог доступным для сравнения.