Введение
PAPER & FORM продаёт бумажные принты и настольные предметы. Приближается перенос на другой сервис, и владелице нужно точно знать, какие заказы вернёт резервная копия. Наличия файла недостаточно: он должен содержать каждый заказ и его позиции в определённой точке восстановления.
Вы оформите небольшой заказ, сохраните архив PostgreSQL в специальном формате, затем добавите другой заказ и поймёте, почему он не входит в архив. Достаточно базовых навыков терминала. База, инструменты и сайт готовы; писать SQL или устанавливать ПО не придётся. Все клиенты, цены и заказы вымышлены; платежей и отправки почты нет.
Работайте с действующим магазином в Original Shop, с командами — в Workstation. Restored Copy — независимая пустая цель для следующей работы; в этом модуле ничего туда не восстанавливайте. Каждый модуль начинается со своих данных. Сохраните программу и uploads/ без изменений. Это упражнение по логическому экспорту, а не полное аварийное восстановление или восстановление к заданному моменту (PITR).
Записать заказ, который должен войти в копию
На этом шаге вы создадите настоящий заказ с позициями. Начните в Original Shop. Синяя полоса показывает исходную базу shop_source. Откройте Explore the collection ↗. В каталоге Print pair стоит $18.00 за штуку, а Desk tray — $26.00. Откройте Orders в верхнем меню, выберите R-101 и прочитайте позицию: два Print pair дают $36.00. Нажмите Download receipt ↓ и прочитайте сохранённый текст. Там есть номер, клиент, товар, количество и итог. Вернитесь через PAPER & FORM.
База данных хранит структурированные записи. Здесь orders содержит номер и клиента заказа, а order_items — его позиции. Каждая позиция ссылается на родительский заказ. Сохранение только имён или итогов потеряет необходимую магазину связь. Страница и квитанция читают настоящие связанные строки.
Перейдите в Workstation. pwd выводит рабочий каталог, ls перечисляет файлы:
pwd
/home/labex/project/shop-backup
ls
Вы увидите backups, shopctl и uploads. Сохраняйте выгрузки в backups/. uploads/packing-note.txt не относится к заданию и должен остаться неизменным. Логический экспорт не включает файлы за пределами базы.
./shopctl запускает подготовленный помощник в текущем каталоге. Его действие identity показывает реальные соединения. Роль — учётная запись базы, определяющая права. Хост и порт указывают сервис базы. Выполните:
./shopctl identity
Найдите источник shop_source с клиентской ролью только для чтения d09_reader и цель shop_copy с доступной для записи ролью d09_copy, обе на 127.0.0.1:5432. Общий сервер не означает общую базу. Роль копии не может подключиться к источнику. Сайт пишет в источник другой ролью. Это границы учебной работы, не защита от системного администратора.
В Original Shop откройте Collection и прокрутите до Place an order. Перед отправкой прочитайте Writing to: shop_source · ORIGINAL SHOP. Введите точно:
| Поле | Значение |
|---|---|
| Reference | R-103 |
| Name | Rae |
| Item | Print pair |
| Quantity | 2 |
Нажмите Place order ↗. Откроется R-103 для Rae с двумя Print pair и итогом $36.00. Это граничный заказ, обязательный для копии. Форма оригинала отклоняет неизвестные номера и номера только для копии без записи данных. Отправка R-104 до сохранения пригодного защищённого cutoff-kept.dump также даёт Keep the earlier point first, ничего не записывая. Если вы имели в виду R-103, вернитесь в Collection и исправьте номер. Это защищает порядок данного упражнения; в производственном магазине обычно не ждут резервной копии для приёма заказов. Если в существующем R-103 неверны клиент, товар или количество, исправьте только эту зарезервированную учебную запись в Workstation:
./shopctl correct source R-103
Помощник показывает реальное назначение и меняет только R-103 на Rae / Print pair / 2. Он отказывается менять исходные базовые номера и сохраняет остальные заказы, поздние записи, загрузки и все архивы. Это явное действие учащегося, а не действие проверки. Исправьте и перечитайте запись перед выгрузкой. Если повторный щелчок использует существующий номер, форма отвечает Already recorded; откройте Orders и прочитайте запись вместо создания дубликатов.
Вернитесь в Workstation. records выводит реальные связанные данные; последние числа — количество и цена за единицу в центах:
./shopctl records source
Найдите R-103 | Rae | Print pair | 2 | 1800 и общий итог $98.00 по трём заказам. Нужный заказ добавлен без изменения R-101 и R-102.
Сохранить согласованный архив специального формата
На этом шаге вы сохраните три подтверждённых заказа. Точка восстановления — состояние базы, зафиксированное экспортом, а не имя или время изменения файла. PostgreSQL pg_dump создаёт согласованный снимок: связанные таблицы берутся из одного представления состояния базы даже при работе других пользователей. В упражнении завершите R-103 до экспорта и дождитесь его окончания перед следующим заказом. Этот порядок делает границу однозначной без сравнения часов.
Оставайтесь в Workstation. pg_dump экспортирует базу, pg_restore читает её архивные форматы. Проверьте версии клиентов:
pg_dump --version
pg_restore --version
Оба должны показать PostgreSQL 14; сервер также версии 14. Старый pg_dump может не работать с новым сервером. Не обходите ошибку версии сохранением пустого файла. Совместимые инструменты уже подготовлены.
Снова покажите соединения перед выбором источника:
./shopctl identity
Сервисы соединений PostgreSQL — сохранённые настройки подключения. service=shop-source выбирает shop_source и роль только для чтения; service=shop-copy — независимую цель. --dbname выбирает это соединение. Всегда указывайте сервис явно, не полагаясь на значения клиента по умолчанию.
--format=custom создаёт сжатый архив PostgreSQL для pg_restore, а не текстовый SQL-скрипт. --file задаёт имя результата. --no-privileges исключает исходные разрешения. Для специального архива pg_dump --no-owner игнорируется: владение пропускают позже параметром --no-owner у pg_restore. Тогда владельцем восстановленных объектов становится целевая роль. Команда читает источник и пишет только указанный локальный файл:
pg_dump --dbname=service=shop-source --format=custom --no-privileges --file=backups/cutoff.dump
Успешная выгрузка обычно ничего не выводит. Не вводите следующий бизнес-заказ до завершения. При ошибке соединения или файла проверьте pwd, ./shopctl identity и выходной путь, затем повторите. Повтор заменяет backups/cutoff.dump; делайте это только пока источник ещё в нужном граничном состоянии. Поздний экспорт захватит поздние данные.
pg_restore --list читает оглавление без импорта:
pg_restore --list backups/cutoff.dump
В начале найдите Format: CUSTOM, dbname: shop_source и совместимые версии выгруженной базы и клиента. Ниже будут orders, order_items, данные, последовательности и ограничения. Это описание структуры, не доказательство наличия верных бизнес-строк. Реальное восстановление и чтение дают более сильное свидетельство.
Проверка испытывает ваш настоящий архив в новой одноразовой базе, включая граничный заказ и его позиции. Она не восстанавливает вкладку Restored Copy. Сохраните архив для следующего шага.
Перед переходом прочитайте результат проверки и сохраните проверенный архив. cp копирует файл под вторым именем. chmod a-w убирает право записи у всех пользователей, защищая оба имени от случайной перезаписи через pg_dump --file:
cp backups/cutoff.dump backups/cutoff-kept.dump
chmod a-w backups/cutoff.dump backups/cutoff-kept.dump
Делайте это только после успешной проверки. Прямая выгрузка в любой защищённый файл теперь завершится Permission denied вместо замены точки. Если исходное имя удалено, cp backups/cutoff-kept.dump backups/cutoff.dump вернёт его байты. Сохранённый файл — вторая локальная копия против обычных ошибок, не внешняя защита от катастроф.
Отличить поздние заказы от сохранённой точки
На этом шаге источник продолжит работу, а архив останется в прежнем состоянии. В Original Shop откройте Collection и перед записью прочитайте Writing to: shop_source · ORIGINAL SHOP. Отправьте:
| Поле | Значение |
|---|---|
| Reference | R-104 |
| Name | Sol |
| Item | Desk tray |
| Quantity | 1 |
Новая запись даёт $26.00. В Orders должны быть R-101, R-102, R-103 и R-104. R-104 подтверждён после окончания pg_dump, поэтому не входит в backups/cutoff.dump. Копия — не живое соединение, продолжающее принимать заказы. Сейчас не заменяйте граничный архив новым экспортом.
В Workstation снова прочитайте источник:
./shopctl records source
Теперь есть R-104 | Sol | Desk tray | 1 | 2600 и итог $124.00. Источник остаётся пригодным к работе: вы не разрушали данные ради восстановления. Повторное оглавление архива всё ещё показывает его исходную структуру:
pg_restore --list backups/cutoff.dump
Проверка восстанавливает архив лишь в одноразовую тестовую базу. Она ожидает R-101—R-103 без R-104. Это доказывает точку восстановления, а не только наличие файла. Оставьте Restored Copy пустой в этом модуле.
Если в R-104 ошибка, ./shopctl correct source R-104 показывает источник и исправляет только существующий учебный заказ на Sol / Desk tray / 1, сохраняя все более ранние записи. Неизвестный номер отклоняется формой: исправьте его и отправьте снова.
Если вы удалили или заменили cutoff.dump, верните прежние сохранённые байты вместо создания будущего снимка. В Workstation chmod u+w возвращает владельцу запись в этот один файл; cp восстанавливает содержимое, а chmod a-w снова защищает:
chmod u+w backups/cutoff.dump
cp backups/cutoff-kept.dump backups/cutoff.dump
chmod a-w backups/cutoff.dump
Если файл удалён, пропустите первую команду и сразу используйте сохранённую копию. Затем повторите проверку. Не удаляйте R-104 и не откатывайте источник: поздние бизнес-записи должны остаться. Если все копии прежней точки действительно потеряны, новый логический экспорт не создаст прошлое. Поэтому предыдущий шаг проверяет и сохраняет защищённую копию до продвижения источника. Следующая независимая работа предоставит ту же точку, чтобы сосредоточиться на безопасном восстановлении.
Резюме
Вы создали настоящий заказ, выгрузили согласованный архив PostgreSQL в специальном формате и отличили сохранённую точку от более позднего исходного заказа. Проверка испытала реальные восстановленные связи в одноразовой базе. Следующая независимая работа откроет сохранённое состояние как пригодную к работе копию магазина.


