WAL, резервная копия и проверяемое восстановление
Библиотека неделю вводила выдачи, после чего диск компьютера перестал читаться. Ограничения таблиц были правильными, приложение использовало транзакции, но это не возвращает потерянный диск. Теперь нужно различать три события: аварийное завершение процесса, потерю хранилища и ошибочное удаление данных человеком. PostgreSQL использует разные механизмы для этих случаев. Проверим доступный начинающему способ восстановления на отдельной пустой базе.
Что сохраняет WAL
При изменении строки PostgreSQL изменяет страницы данных в памяти и формирует записи журнала предзаписи, WAL. Правило предзаписи требует сохранить необходимые записи журнала прежде, чем соответствующие изменённые страницы попадут на постоянное хранилище. После сбоя сервер использует журнал для восстановления согласованного состояния. Commit при обычной настройке synchronous_commit ждёт локального сохранения WAL; запись самой страницы таблицы может произойти позже.
Это объясняет, почему Commit не обязательно означает немедленную запись каждого изменённого файла таблицы. Журнал содержит информацию, необходимую восстановлению. Контрольная точка, checkpoint, ограничивает объём последующего восстановления, записывая накопленные изменения и фиксируя состояние. Частота таких операций влияет на нагрузку, но менять настройки наугад по одному маленькому запросу не нужно.
Гарантии зависят и от устройства хранения, которое должно честно выполнять запросы синхронизации. Отключение fsync ради быстрого теста нельзя переносить на важные данные. Асинхронный Commit также меняет окно возможной потери последних подтверждённых транзакций при аварии. Для учебного сервера оставьте безопасные стандартные настройки и сначала научитесь объяснять, что именно подтверждает выбранный режим.
WAL работающего экземпляра сам по себе не является независимой резервной копией всего содержимого. Если все нужные файлы и журнал находились на погибшем диске, механизм аварийного восстановления не создаст их заново. Реплика тоже может быстро повторить ошибочное DELETE. Для возврата к состоянию до ошибки нужны сохранённые копии и, при соответствующей схеме, архив журнала с возможностью восстановления на момент времени.
Логический архив
Для нашей маленькой библиотеки подходит pg_dump. Он выгружает определения объектов и данные одной базы, используя согласованный снимок. Архив custom поддерживает обработку через pg_restore. Он не копирует весь сервер, пользователей и все внешние настройки. Если приложение зависит от ролей, расширений или отдельных файлов, их восстановление необходимо планировать дополнительно.
Перед опытом выполните знакомую проверку:
SELECT count(*) AS loans,
count(*) FILTER (WHERE returned_on IS NULL) AS active
FROM club.loans;На исходном seed ожидаются loans=3 и active=2. Команда FILTER считает только строки, удовлетворяющие условию, внутри отдельного агрегата. Запишите эти числа вместе с именем базы, временем копии и версией сервера: без ожидаемого состояния труднее понять, что вернулось после восстановления.
Из каталога скачанных лабораторий запустите:
pg_dump --format=custom --no-owner --file=library.dump "$DB_LAB_URL"
createdb db_course_library_restore_2026
export DB_RESTORE_URL='postgresql://localhost/db_course_library_restore_2026'
pg_restore --exit-on-error --single-transaction --no-owner --no-privileges --dbname="$DB_RESTORE_URL" library.dump
psql "$DB_RESTORE_URL" -f tests.sqlURL и локальную роль задайте по настройке из первого урока. Цель должна быть только что созданной пустой базой. Если createdb сообщает совпадение имени, остановитесь и выберите новое имя. Не продолжайте в существующей базе. Не запускайте setup перед восстановлением: архив сам создаёт схему club. Здесь нет --clean и автоматического удаления прежних объектов.
--single-transaction собирает восстановление в одну транзакцию, а --exit-on-error останавливает его при ошибке. Для небольшого архива такой режим позволяет не оставить частично восстановленную базу после неудачи. Для очень больших копий, параллельного восстановления и расширений понадобятся другие решения. Отсутствие владельцев и привилегий в нашем запуске удобно для локального упражнения, но не восстанавливает промышленную модель доступа.
Проверяем доступность данных
Успех pg_restore означает, что команды завершились; он не доказывает работу приложения целиком. tests.sql сравнивает seed, NULL, связи и ограничения в восстановленной базе и откатывает свои пробные изменения. Дополнительно выполните JOIN из четвёртого урока и убедитесь, что Анна по-прежнему имеет две активные выдачи одной книги на разных экземплярах.
Можно проверить защиту экземпляра отдельно:
BEGIN;
INSERT INTO club.loans
(id, member_id, copy_id, borrowed_on, due_on)
VALUES (2000, 3, 100, DATE '2026-09-18', DATE '2026-10-02');
ROLLBACK;Ожидается unique_violation: экземпляр 100 уже выдан. Это намеренная ошибка. В интерактивном psql выполните ROLLBACK после неё; не помещайте такой отрицательный тест в общий файл с ON_ERROR_STOP без обработчика. Автоматический tests.sql ловит ожидаемую ошибку внутри специального блока и проверяет именно её тип.
Цели восстановления
RPO описывает допустимую потерю данных во времени: копия вчерашнего вечера оставляет риск потерять сегодняшние изменения. RTO описывает допустимое время восстановления работы. Оба значения задаются потребностями клуба, а проверяются опытом. Если копия снимается раз в сутки, обещание потери не более минуты не выполняется только наличием файла dump.
Измерьте время восстановления, проверки и переключения приложения отдельно. Проверяйте, что копия доступна при отказе основного устройства и что известны необходимые секреты доступа. Сам архив содержит личные сведения читателей; хранение и права доступа относятся к задаче резервирования. Для курса достаточно локального собственного архива без реальных персональных данных. Не восстанавливайте случайный чужой dump: определения объектов могут содержать исполняемый код.
Самостоятельная лаборатория
Отведите 40–60 минут. Снимите копию golden seed, создайте отдельную пустую базу, восстановите и выполните tests.sql. Запишите размер архива, время операций, версию pg_dump и сервера, количество строк и результат отрицательного теста. Исходную базу не изменяйте. Критерий готовности — проверенные данные и ограничения, а не только существование library.dump.
Разбор
WAL решает восстановление после сбоя при наличии нужного хранилища. Независимая копия помогает при потере этого хранилища. Проверенный restore превращает файл копии в наблюдаемую способность вернуть работу. Если требования потребуют меньшего RPO, изучите базовую физическую копию вместе с непрерывным архивированием WAL и восстановлением на момент времени; одного учащения ручного pg_dump может быть недостаточно.
Первичные источники
PostgreSQL: WAL, логическая копия, pg_restore, непрерывное архивирование.