В прошлом уроке база научилась выдерживать тысячи клиентов, а в уроке про репликацию переживать смерть сервера. Но от одной беды не спасает ни то, ни другое: от человека, который по ошибке удалил таблицу заказов. Реплика повторит удаление через миллисекунды. Последний урок раздела про то, как вернуть данные на любую секунду, как расширять PostgreSQL и как понять, что с ним происходит прямо сейчас.
Фотография и дневник
Представь, что раз в неделю ты фотографируешь свою комнату, а между фотографиями записываешь в дневник каждое действие: «передвинул стол», «повесил полку». Если в четверг в 15:00 что-то сломалось, берёшь фото воскресенья и повторяешь по дневнику все действия до четверга 14:59. Комната восстановлена ровно на ту минуту, которая тебе нужна.
Ровно так устроены бэкапы больших баз. Фотография это полная копия файлов кластера. Дневник это журнал WAL, который мы уже видели в уроке про репликацию: каждое изменение сначала пишется туда. Вместе они дают восстановление на момент времени, PITR.
Логический и физический бэкап
В уроке про права мы снимали копию через pg_dump. Это логический бэкап: команды, которые заново создают таблицы и вставляют строки. Есть и второй вид, физический: копия файлов каталога данных байт в байт.
Логический (pg_dump) | Физический (pg_basebackup + WAL) | |
|---|---|---|
| Что внутри | SQL-команды и данные | файлы кластера |
| Объём работы | одна база или таблица | весь кластер |
| Восстановление | медленное: заново вставить строки и построить индексы | быстрое: положить файлы на место |
| На любую секунду | нет, только на момент снимка | да, вместе с архивом WAL |
| Между версиями | да | нет, только та же основная версия |
Для маленьких баз и переноса данных хватает pg_dump. Для рабочей базы магазина нужен физический бэкап с архивом журнала.
Архив журнала и полная копия
Первый шаг: научить сервер складывать каждый заполненный файл журнала в архив. Это две настройки в postgresql.conf:
archive_mode = on
archive_command = 'test ! -f /mnt/wal_archive/%f && cp %p /mnt/wal_archive/%f'
PostgreSQL вызывает archive_command для каждого готового файла журнала: %p это путь к файлу, %f его имя. Команда из документации копирует файл в архив и отказывается перезаписать уже существующий. Включение archive_mode требует перезапуска сервера. В песочнице архив выключен:
SELECT name, setting
FROM pg_settings
WHERE name IN ('wal_level', 'archive_mode', 'archive_command')
ORDER BY name;
name | setting
-----------------+------------
archive_command | (disabled)
archive_mode | off
wal_level | replica
(3 rows)
Второй шаг: полная копия, та самая фотография. Её снимает уже знакомый по репликации pg_basebackup:
pg_basebackup -h 10.0.0.1 -U replicator \
-D /backups/2026-10-09 -Ft -z -X stream -P
-Ft -z складывает копию в сжатые tar-архивы. Копию снимают регулярно, например раз в сутки, а журнал архивируется непрерывно.
Восстановление на минуту до ошибки
В четверг в 15:00 кто-то выполнил DROP TABLE orders. Восстанавливаем базу на 14:59:
-
Останавливаем сервер и откладываем испорченный каталог данных в сторону.
-
Распаковываем последнюю полную копию в пустой каталог данных.
-
Говорим серверу, откуда брать журнал и где остановиться, в
postgresql.conf:restore_command = 'cp /mnt/wal_archive/%f %p' recovery_target_time = '2026-10-08 14:59:00+03' -
Создаём в каталоге данных пустой файл
recovery.signal, он переводит сервер в режим восстановления. -
Запускаем сервер. Он берёт файлы журнала из архива, повторяет изменения по порядку и останавливается на 14:59.
Таблица orders снова на месте, со всеми заказами до 14:59. Заказы, сделанные после ошибки, придётся переносить отдельно, поэтому восстановление сначала делают на отдельный сервер, а потом решают, что из него забрать.
Руками этот процесс почти не делают. Его автоматизируют программы вроде pgBackRest, WAL-G и Barman: они снимают полные копии по расписанию, сжимают и шифруют архив, хранят его в облаке и восстанавливают одной командой.
Сколько можно потерять и сколько чинить
Про бэкапы договариваются двумя числами:
- RPO: сколько данных бизнес готов потерять. С ночным
pg_dumpэто до суток, с архивом WAL минуты и меньше. - RTO: сколько времени можно чинить. Восстановить терабайт из
pg_dumpэто часы, из физической копии заметно быстрее, а переключение на реплику это минуты.
И три правила, которые мы уже встречали:
- Бэкап, который не восстанавливали, не бэкап. Регулярно поднимай копию на отдельном сервере и проверяй данные.
- Бэкап хранят отдельно. Не на том же диске и лучше не в том же дата-центре.
- Реплика не бэкап. Она повторяет ошибки мгновенно.
Как эти числа выглядят в бою и как устроен failover, разобрано в уроке про внутренности PostgreSQL.
урок из курса
Урок из курса «PostgreSQL с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.