Сделайте первое упражнение намеренно небольшим
Это упражнение создаёт игрушечную базу данных заметок и одно вложение, захватывает и то, и другое, затем восстанавливает их в новую базу данных и каталог. Используйте одноразовую машину Linux с сервером PostgreSQL 17 и соответствующими клиентскими утилитами, Bash и GNU coreutils. Она не должна содержать производственных данных и не должна иметь соединения с производственными приложениями, исходящей почтой или запланированными заданиями. Используйте только архив, созданный в этом упражнении.
Команды предполагают предварительно настроенную роль базы данных, не являющуюся суперпользователем, с именем restore_lab, которой разрешено создавать тестовые базы данных, и вход в ОС с тем же именем, который может аутентифицироваться локально. Сокет PostgreSQL находится /var/run/postgresql на порту 5432. Попросите администратора подготовить эту учётную запись в одноразовой среде; это руководство не изменяет правила доступа к базе данных. Проверьте конечную точку перед созданием чего-либо:
psql -h /var/run/postgresql -p 5432 -U restore_lab -d postgres -c '\conninfo' &&
pg_dump --version &&
pg_restore --version
Остановитесь, если хост, учётная запись или версия неожиданны. Держите клиенты и сервер на одной мажорной версии для этого первого упражнения. pg_dump не может создать дамп сервера новее своей собственной мажорной версии, и более старый целевой сервер восстановления обычно не гарантирует совместимость. См. ограничения версии pg_dump. Запускайте каждый блок отдельно и останавливайтесь при ошибке. && защитные проверки предотвращают выполнение последующих команд во вставленном блоке после сбоя; никогда не переходите к следующему блоку после неудачного создания базы данных или каталога.
Создайте запись и соответствующий ей файл
Имена offvps_restore_source и offvps_restore_target должны быть неиспользованными. Существующая база данных — это причина остановиться и выбрать новое изолированное упражнение, а не причина удалить её. Создайте новое рабочее пространство файловой системы и исходную базу данных:
umask 077 &&
lab=$(mktemp -d "$PWD/offvps-restore.XXXXXX") &&
mkdir "$lab/source" "$lab/source/uploads" "$lab/bundle" "$lab/restore" &&
createdb -h /var/run/postgresql -p 5432 -U restore_lab \
--template=template0 offvps_restore_source
Новое рабочее пространство избегает перезаписи существующего каталога. mktemp создаёт уникальный каталог; createdb создаёт новую базу данных из выбранного шаблона. Сохраните эти два маркера:
psql -X -v ON_ERROR_STOP=1 -h /var/run/postgresql -p 5432 \
-U restore_lab -d offvps_restore_source \
-c "CREATE TABLE notes (
id integer PRIMARY KEY,
body text NOT NULL,
attachment text NOT NULL
);
INSERT INTO notes VALUES (1, 'restore-marker-01', 'marker.txt');" &&
printf '%s\n' 'restore-marker-01' > "$lab/source/uploads/marker.txt"
Запись указывает, какой файл принадлежит заметке, и оба содержат один и тот же маркер. Это делает видимым отсутствующее вложение или несовпадающую копию. -X избегает персональных настроек запуска psql, а ON_ERROR_STOP останавливается при ошибке SQL; см. параметры написания скриптов psql. В этот игрушечный набор данных не пишет никакое приложение.
Захватите базу данных и файлы как единый набор восстановления
pg_dump -h /var/run/postgresql -p 5432 -U restore_lab \
--format=custom --file="$lab/bundle/notes.dump" offvps_restore_source &&
cp -a "$lab/source/uploads" "$lab/bundle/uploads" &&
pg_restore --list "$lab/bundle/notes.dump"
Архив в пользовательском формате читается pg_restore; обычный SQL-дамп следует другой процедуре восстановления. Просмотр списка архива помогает убедиться, что ожидаемая таблица и записи данных присутствуют. Согласованный дамп базы данных не синхронизирует автоматически внешние загрузки. Для реального приложения используйте его документированную процедуру обслуживания или приостановки записи, чтобы дерево файлов и база данных описывали одну и ту же точку во времени. Игрушечное упражнение уже находится в покое.
Запишите версию базы данных, выпуск приложения, начало/окончание захвата и путь к файлу рядом с пакетом. Храните реальные учётные данные отдельно с соответствующим контролем доступа. Дамп отдельной базы данных не захватывает глобальные роли и табличные пространства; реальный план восстановления должен учитывать и их. Область применения описана в руководстве PostgreSQL по SQL-дампам.
Восстанавливайте в новые цели, не очищая существующую
createdb -h /var/run/postgresql -p 5432 -U restore_lab \
--template=template0 offvps_restore_target &&
pg_restore -h /var/run/postgresql -p 5432 -U restore_lab \
--dbname=offvps_restore_target --no-owner --no-acl \
--single-transaction "$lab/bundle/notes.dump" &&
mkdir "$lab/restore/uploads" &&
cp -a "$lab/bundle/uploads/." "$lab/restore/uploads/"
Целевая база данных создаётся пустой. Восстановление намеренно пропускает --clean, что могло бы удалить существующие объекты. --single-transaction заставляет восстановление этой небольшой базы данных либо успешно завершиться как единое целое, либо остановиться без применения частичных изменений; это нельзя комбинировать с параллельными заданиями. --no-owner и --no-acl упрощает владение для этой тестовой роли, поэтому это упражнение не проверяет производственные роли или разрешения приложения. См. pg_restore.
Копирование файлов нацелено на новый каталог восстановления, оставляя источник нетронутым. GNU cp -a пытается сохранить атрибуты файлов; проверьте владение и доступ для учётной записи, которая будет запускать реальное приложение. Копирование байтов не является проверкой разрешений приложения. См. опция archive в cp.
Проверяйте взаимосвязь, а не только коды выхода
psql -X -h /var/run/postgresql -p 5432 -U restore_lab \
-d offvps_restore_target -c "SELECT id, body, attachment FROM notes;" &&
cat "$lab/restore/uploads/marker.txt"
Ожидаемые результаты — одна строка с ID 1, телом restore-marker-01 и вложением marker.txt, плюс файл, содержащий restore-marker-01. Проверьте, что источник по-прежнему содержит свою исходную строку и файл. Для вашего реального приложения также наведите изолированный экземпляр на восстановленную базу данных и каталог загрузок, откройте репрезентативные записи, загрузите вложение и проверьте предполагаемые разрешения на вход. При этом удерживайте обратные вызовы, почту и задания в ограниченном состоянии.
Запишите, что вы доказали и что осталось
| Запись | Что захватывать |
|---|---|
| Точка восстановления | Время захвата и самая новая ожидаемая запись |
| Длительность восстановления | Время начала/окончания и ручные шаги |
| Проверки | Строка базы данных, содержимое вложения и проверки приложения |
| Исключения | Отсутствующие роли, разрешения, конфигурация или зависимости |
| Следующее упражнение | Триггер, например изменение схемы, хранилища или развёртывания |
Ожидаемые результаты выше — это критерии упражнения, а не результаты, уже наблюдавшиеся OffVPS. Поскольку первое упражнение хранит все файлы на одной машине, оно не обеспечивает защиты от потери этой машины. Реальный план нужен с защищённой копией в отдельном домене отказа, пригодными для использования ключами расшифровки, сроком хранения и проверенным путём извлечения. Перед последующей очисткой проверьте точные имена одноразовой базы данных и каталога; держите производство вне этого процесса.
Повторяйте упражнение после важных изменений и фиксируйте сбои так же тщательно, как успехи. Необязательный сервис резервного копирования не доказывает время восстановления вашего приложения. Продолжите с планирования запланированного задания когда будете готовы автоматизировать захват, сохраняя отдельное упражнение по восстановлению.
Использованная документация
Основные ссылки для этой страницы. Проверьте документацию для версии, установленной в вашей среде.