Раздел 33 · PostgreSQL с нуля

Бэкапы, расширения и мониторинг

junior~25 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В прошлом уроке база научилась выдерживать тысячи клиентов, а в уроке про репликацию переживать смерть сервера. Но от одной беды не спасает ни то, ни другое: от человека, который по ошибке удалил таблицу заказов. Реплика повторит удаление через миллисекунды. Последний урок раздела про то, как вернуть данные на любую секунду, как расширять 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:

  1. Останавливаем сервер и откладываем испорченный каталог данных в сторону.

  2. Распаковываем последнюю полную копию в пустой каталог данных.

  3. Говорим серверу, откуда брать журнал и где остановиться, в postgresql.conf:

    restore_command = 'cp /mnt/wal_archive/%f %p'
    recovery_target_time = '2026-10-08 14:59:00+03'
  4. Создаём в каталоге данных пустой файл recovery.signal, он переводит сервер в режим восстановления.

  5. Запускаем сервер. Он берёт файлы журнала из архива, повторяет изменения по порядку и останавливается на 14:59.

Таблица orders снова на месте, со всеми заказами до 14:59. Заказы, сделанные после ошибки, придётся переносить отдельно, поэтому восстановление сначала делают на отдельный сервер, а потом решают, что из него забрать.

Руками этот процесс почти не делают. Его автоматизируют программы вроде pgBackRest, WAL-G и Barman: они снимают полные копии по расписанию, сжимают и шифруют архив, хранят его в облаке и восстанавливают одной командой.

Сколько можно потерять и сколько чинить

Про бэкапы договариваются двумя числами:

  • RPO: сколько данных бизнес готов потерять. С ночным pg_dump это до суток, с архивом WAL минуты и меньше.
  • RTO: сколько времени можно чинить. Восстановить терабайт из pg_dump это часы, из физической копии заметно быстрее, а переключение на реплику это минуты.

И три правила, которые мы уже встречали:

  • Бэкап, который не восстанавливали, не бэкап. Регулярно поднимай копию на отдельном сервере и проверяй данные.
  • Бэкап хранят отдельно. Не на том же диске и лучше не в том же дата-центре.
  • Реплика не бэкап. Она повторяет ошибки мгновенно.

Как эти числа выглядят в бою и как устроен failover, разобрано в уроке про внутренности PostgreSQL.

урок из курса

Урок из курса «PostgreSQL с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.