Перейти к содержимому

19 Занятие 19: Резервное копирование / Использование pg_probackup

Исходная страница в нативном Markdown: Резервное копирование / Использование pg_probackup
Примечание

Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета. HTML source: pgpro_19_probackup_2.html Archive: PGPRO-handouts-16.zip Страниц PDF: 38

Page 1: Резервное копирование / Использование pg_probackup

Авторские права

© Postgres Professional, 2023–2026 Авторы: Алексей Береснев, Илья Баштанов, Павел Толмачев, Игорь Гнатюк Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)

Использование материалов курса

Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.

Обратная связь

Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru

Отказ от ответственности

Компания Postgres Professional не несет никакой ответственности за любые повреждения и убытки, включая потерю дохода, нанесенные прямым или непрямым, специальным или случайным использованием материалов курса. Компания Postgres Professional не предоставляет каких-либо гарантий на материалы курса. Материалы курса предоставляются на основе принципа «как есть» и компания Postgres Professional не обязана предоставлять сопровождение, поддержку, обновления, расширения и изменения.

Page 2: Темы

  • Инкрементальные копии
  • Способы восстановления
  • Синхронизация

Page 3: Инкрементальные копии

Разностное копирование (DELTA)

  • Копирование изменений (PTRACK)
  • Страничное копирование (PAGE)
  • Объединение копий

Page 4: Копирование DELTA

Source slide page 4: Копирование DELTA{#source-figure-004 caption=“Source slide page 4: Копирование DELTA”}

Полная и инкрементальные копии образуют цепочку

  • Разностное копирование — вариант инкрементального
  • Читаются все файлы данных, но в копию попадают только измененные с последнего копирования страницы

Комментарии преподавателя

Инкрементальная копия включает в себя все изменения, произошедшие после создания какой-либо другой копии.

Полная копия и набор последующих инкрементальных копий образуют цепочку. При восстановлении кластера из инкрементальной копии pg_probackup восстанавливает родительскую полную копию, а затем применяет к ней последовательно инкрементальные копии, останавливаясь после целевой.

Утилита pg_probackup поддерживает три режима инкрементального резервного копирования: DELTA, PAGE и PTRACK.

Режим DELTA — разностное копирование. Страницы файлов в каталоге данных сравниваются со страницами из последней резервной копии. В новую резервную копию попадают только измененные с момента последнего копирования страницы.

Достоинство режима DELTA — его простота: не требуется архив WAL и не надо устанавливать дополнительные расширения. Однако есть и недостаток: объем ввода-вывода может оказаться почти таким же, как при полном резервном копировании.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-MODES-D ELTA

Page 5: Восстановление

Source slide page 5: Восстановление{#source-figure-005 caption=“Source slide page 5: Восстановление”}

Команда restore восстанавливает кластер из копии

  • По умолчанию выбирается последняя копия
  • Если указана инкрементальная копия, применяется цепочка копий, начиная с полной

Комментарии преподавателя

Если команде restore утилиты указать инкрементальную копию, pg_probackup восстановит родительскую полную копию и затем последовательно применит нужные инкрементальные копии.

Если идентификатор копии не указан, выполняется восстановление из самой последней имеющейся копии (включая копии из цепочки, если последняя копия — инкрементальная).

Page 6: Копирование DELTA

Создадим базу данных, к которой будет подключаться роль backup.

=> CREATE DATABASE pgpro_probackup_2 OWNER backup TEMPLATE templateprobackup;
CREATE DATABASE
=> \c pgpro_probackup_2
You are now connected to database "pgpro_probackup_2" as user "student".

Мы будем запускать утилиту локально от имени пользователя ОС student, а агент на удаленном сервере будет обращаться к файлам кластера от имени postgres. Необходимые настройки в виртуальной машине курса уже произведены. Подготовим локальный каталог копий, владелец файлов — student.

student$ sudo mkdir /var/probackup
student$ sudo chown student: /var/probackup
student$ pg_probackup init \
  -B /var/probackup
INFO: Backup catalog '/var/probackup' successfully initialized

Добавим в локальный каталог копий экземпляр БД, работающий на целевом сервере.

student$ pg_probackup add-instance \
  -B /var/probackup --instance ent-16 \
  -D /var/lib/pgpro/ent-16 \
  --remote-host=localhost \
  --remote-user=postgres
INFO: Instance 'ent-16' successfully initialized

Не забудем о настройках конфигурации:

student$ pg_probackup set-config \
  -B /var/probackup --instance ent-16 \
  --log-level-console=ERROR \
  --allow-group-access \
  --remote-host=localhost \
  --remote-user=postgres \
  -d pgpro_probackup_2 \
  -U backup

Каталог PGDATA принадлежит пользователю ОС postgres и группе postgres, и экземпляр обычно запускается от имени postgres. Если указан параметр –allow-group-access, при восстановлении дополнительно выдаются права на чтение и доступ в каталог группе postgres — это позволит в будущем выполнять резервное копирование от имени членов группы, не используя максимальные привилегии root. Сначала сформируем полную резервную копию удаленного сервера, используя потоковую доставку записей WAL:

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b FULL \
  --stream

В каталоге резервных копий появилась запись:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
====================================================
 Instance  Version  ID      Recovery Time                  Mode  WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN  Stop LSN   Status
==========================================================================================
====================================================
 ent-16    16       TIUPRH  2026-07-27 23:47:51.513336+03  FULL  STREAM    1/0   36s
328MB  16MB  none    1,00  0/C000028  0/C001820  OK

Произведем какие-нибудь изменения, например, создадим таблицу:

=> CREATE TABLE IF NOT EXISTS t1 (
  msg text
);
CREATE TABLE

Page 7: Page 7

И запишем в нее данные:

=> INSERT INTO t1 VALUES ('Полная копия создана.'), ('Теперь сделаем разностную.');
INSERT 0 2

Получим разностную резервную копию:

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b DELTA --stream

Что теперь в каталоге копий?

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
======================================================
 Instance  Version  ID      Recovery Time                  Mode   WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN  Stop LSN   Status
==========================================================================================
======================================================
 ent-16    16       TIUPSI  2026-07-27 23:48:21.207076+03  DELTA  STREAM    1/1    5s
2758kB  16MB  none    1,00  0/E000028  0/E0001A0  OK
 ent-16    16       TIUPRH  2026-07-27 23:47:51.513336+03  FULL   STREAM    1/0   36s
328MB  16MB  none    1,00  0/C000028  0/C001820  OK

Обратите внимание, насколько разностная копия меньше полной. Восстановим кластер из последней копии. Остановим экземпляр:

student$ sudo systemctl stop postgrespro-ent-16.service

Удалим содержимое PGDATA.

student$ sudo rm -rf /var/lib/pgpro/ent-16/*

При восстановлении указываем разностную копию:

student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  -i TIUPSI

Запускаем экземпляр.

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2
=> SELECT * FROM t1;
            msg
----------------------------
 Полная копия создана.
 Теперь сделаем разностную.
(2 rows)

Мы восстановили данные, использовав цепочку из полной и разностной копий.

Page 8: Объединение копий

Source slide page 8: Объединение копий{#source-figure-008 caption=“Source slide page 8: Объединение копий”}

Команда merge объединяет родительскую полную копию и дочерние инкрементальные копии в одну общую

  • Не нагружает сеть передачей данных

Комментарии преподавателя

Инкрементальная резервная копия строится быстрее полной и занимает меньше места. Однако по мере роста цепочки занимаемый объем и время восстановление будут увеличиваться.

Утилита pg_probackup позволяет объединить цепочку копий в одну полную копию командой merge.

Передав команде merge идентификатор последней инкрементальной копии в цепочке, мы получим единую полную копию, содержащую данные родительской полной копии со всеми изменениями, накопленными в цепочке инкрементальных. Все копии цепочки удаляются и остается единственная объединенная полная копия.

Указав команде идентификатор родительской копии, мы получим объединенную копию, включающую родительскую полную и первую инкрементальную.

При объединении вся работа производится в каталоге резервных копий, команда merge не передает данные по сети.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-MERGING -BACKUPS

Page 9: Объединение копий

Еще раз изменим данные: создадим базу данных, которая нам понадобится в дальнейшем.

=> CREATE DATABASE pgpro_probackup_2_bis;
CREATE DATABASE

Получим вторую разностную резервную копию:

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b DELTA --stream

Состояние каталога копий:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
========================================================
 Instance  Version  ID      Recovery Time                  Mode   WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN   Stop LSN    Status
==========================================================================================
========================================================
 ent-16    16       TIUPTT  2026-07-27 23:49:12.963247+03  DELTA  STREAM    1/1   20s
18MB  16MB  none    1,00  0/10000028  0/100003C0  OK
 ent-16    16       TIUPSI  2026-07-27 23:48:21.207076+03  DELTA  STREAM    1/1    5s
2758kB  16MB  none    1,00  0/E000028   0/E0001A0   OK
 ent-16    16       TIUPRH  2026-07-27 23:47:51.513336+03  FULL   STREAM    1/0   36s
328MB  16MB  none    1,00  0/C000028   0/C001820   OK

В информации о резервной копии есть номер родительской копии:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT | grep 'parent-backup-id'
parent-backup-id = 'TIUPSI'

Третья копия, последняя в цепочке, содержит изменения данных, произошедшие после построения копии с этим идентификатором. По мере добавления инкрементальных копий они будут занимать все больше дискового пространства. Можно выполнить полное копирование и удалить все предыдущие копии, но удобнее воспользоваться объединением копий.

student$ pg_probackup merge \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT

В результате имеем единственную полную копию, объединяющую в себе три предыдущие:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
======================================================
 Instance  Version  ID      Recovery Time                  Mode  WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN   Stop LSN    Status
==========================================================================================
======================================================
 ent-16    16       TIUPTT  2026-07-27 23:49:12.963247+03  FULL  STREAM    1/0   22s
335MB  16MB  none    1,00  0/10000028  0/100003C0  OK

Сохраним эту копию для дальнейшей демонстрации.

Page 10: Копирование PTRACK

Source slide page 10: Копирование PTRACK{#source-figure-010 caption=“Source slide page 10: Копирование PTRACK”}

Механизм PTRACK отслеживает изменения страниц

  • В резервную копию помещаются лишь измененные страницы, обнаруженные PTRACK
  • Требуется расширение ptrack

Комментарии преподавателя

PTRACK — еще один режим инкрементального резервного копирования экземпляра Postgres Pro. В копию попадают только изменившиеся страницы, но, в отличие от DELTA, утилите не требуется сравнивать данные с резервной копией: она получает список страниц с помощью механизма PTRACK.

Механизм PTRACK встроен в ядро Postgres Pro Enterprise. Он отслеживает и отмечает модификации страниц в специальной карте и предоставляет API для получения списка файлов, измененных с произвольного момента LSN, и битовых карт измененных в этих файлах страниц.

https://postgrespro.ru/docs/enterprise/16/ptrack

Утилита pg_probackup получает список страниц, подлежащих копированию, запрашивая изменения, произошедшие после создания предыдущей резервной копии. Поскольку для этого не требуется читать файлы данных и последнюю резервную копию, этот режим инкрементального резервного копирования может оказаться самым быстрым, особенно в сценариях, когда интенсивно изменяются одни и те же страницы.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-MODES-P TRACK

Page 11: Копирование PTRACK

Подключим библиотеку PTRACK к экземпляру.

=> ALTER SYSTEM SET shared_preload_libraries = 'ptrack';
ALTER SYSTEM

Экземпляр необходимо перезагрузить.

student$ sudo systemctl restart postgrespro-ent-16.service

Установим расширение в базу pgpro_probackup_2.

student$ psql pgpro_probackup_2
=> CREATE EXTENSION IF NOT EXISTS ptrack;
CREATE EXTENSION

Необходимо задать значение параметра ptrack.map_size, рекомендуется 1/1024 объема кластера Postgres Pro:

=> ALTER SYSTEM SET ptrack.map_size = '1MB';
ALTER SYSTEM

Изменение этого параметра также требует перезапуска.

student$ sudo systemctl restart postgrespro-ent-16.service

Существующая полная копия была сделана до того, как PTRACK стал отслеживать изменения, поэтому для демонстрации работы PTRACK нам потребуется новая полная копия.

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b FULL \
  --allow-group-access \
  --stream

Добавим в таблицу еще одну строку.

student$ psql pgpro_probackup_2
=> INSERT INTO t1 VALUES ('Проверим PTRACK.');
INSERT 0 1

Теперь выполним инкрементальное резервное копирование в режиме PTRACK.

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b PTRACK \
  --allow-group-access \
  --stream

В каталоге резервных копий появилась инкрементальная копия:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
=========================================================
 Instance  Version  ID      Recovery Time                  Mode    WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN   Stop LSN    Status
==========================================================================================
=========================================================
 ent-16    16       TIUPW4  2026-07-27 23:50:30.218220+03  PTRACK  STREAM    1/1    2s
1201kB  16MB  none    1,00  0/14000028  0/14002630  OK
 ent-16    16       TIUPV3  2026-07-27 23:49:57.033426+03  FULL    STREAM    1/0   35s
336MB  16MB  none    1,00  0/12000028  0/120001A0  OK
 ent-16    16       TIUPTT  2026-07-27 23:49:12.963247+03  FULL    STREAM    1/0   22s
335MB  16MB  none    1,00  0/10000028  0/100003C0  OK

Восстановление в данном случае производится так же, как и для разностных копий. Однако, какая копия будет использована для восстановления, если явно не указать идентификатор?

student$ sudo systemctl stop postgrespro-ent-16.service

Очистим каталог данных.

student$ sudo rm -rf /var/lib/pgpro/ent-16/*

Page 12: Page 12

Восстанавливаем кластер, не указывая идентификатор копии.

student$ pg_probackup restore \
  -B /var/probackup --instance ent-16

Запускаем экземпляр.

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2
=> SELECT * FROM t1;
            msg
----------------------------
 Полная копия создана.
 Теперь сделаем разностную.
 Проверим PTRACK.
(3 rows)

Итак, была использована самая свежая копия. Удалим эти копии, больше они не потребуются.

student$ pg_probackup delete \
  -B /var/probackup --instance ent-16 \
  -i TIUPV3

PTRACK тоже больше не нужен.

=> ALTER SYSTEM RESET ALL;
ALTER SYSTEM
=> DROP EXTENSION ptrack;
DROP EXTENSION

Мы перезапустим экземпляр позже.

Page 13: Копирование PAGE

Source slide page 13: Копирование PAGE{#source-figure-013 caption=“Source slide page 13: Копирование PAGE”}

В архиве должны быть все сегменты WAL, записанные после предыдущей копии

Комментарии преподавателя

При наличии архива WAL для создания инкрементальных копий можно использовать еще один режим инкрементального резервного копирования pg_probackup — страничное копирование (PAGE).

При копировании PAGE pg_probackup сканирует все записи WAL в архиве, начиная с момента создания предыдущей полной или инкрементальной копии, и определяет по ним список изменившихся страниц. При этом необходимо, чтобы в архиве присутствовали все файлы WAL, сгенерированные после предыдущей копии.

Режим PAGE особенно эффективен, когда в базах данных происходит немного изменений. Если же объем журнальных файлов сравним с общим объемом файлов базы данных, ускорение будет незначительным, однако объем инкрементальной копии все равно будет меньше, чем полной.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-MODES-P AGE

Page 14: Восстановление

Source slide page 14: Восстановление{#source-figure-014 caption=“Source slide page 14: Восстановление”}

Удаленное восстановление с обменом данными по SSH

Комментарии преподавателя

Архив WAL заполняется с целевого сервера командой pg_probackup archive-push (указанной в конфигурационном параметре archive_command) по SSH. И при восстановлении целевой сервер будет читать необходимые сегменты журнала по SSH командой pg_probackup archive-get (указанной в параметре restore_command).

Здесь мы имеем дело с удаленным восстановлением. Поэтому при вызове pg_probackup restore требуется указать два набора параметров.

Remote-параметры указывают на целевой сервер с восстанавливаемым экземпляром:

● –remote-host — адрес целевого сервера;

● –remote-user — владелец экземпляра (postgres);

● –remote-port — порт SSH.

Archive-параметры указывают на сервер резервного копирования, хранящий архив WAL:

● –archive-host — адрес сервера резервного копирования;

● –archive-user — владелец каталога резервных копий;

● –archive-port — порт SSH.

Archive-параметры используются, чтобы сформировать на целевом сервере значение параметра restore_command.

Page 15: Копирование PAGE

Подготовим экземпляр к работе с архивацией WAL.

=> ALTER SYSTEM SET archive_mode = on;
ALTER SYSTEM

Для команды архивирования целевым является сервер резервного копирования, здесь ему соответствует localhost. Команда архивирования будет подключаться к серверу по SSH под именем владельца каталога резервных копий — пользователя student.

=> ALTER SYSTEM SET archive_command =
' pg_probackup archive-push'
' -B /var/probackup --instance=ent-16'
' --wal-file-path=%p'
' --wal-file-name=%f'
' --remote-host=localhost'
' --remote-user=student';
ALTER SYSTEM

Экземпляр необходимо перезапустить.

student$ sudo systemctl restart postgrespro-ent-16.service
student$ psql pgpro_probackup_2

Посмотрим содержимое архива WAL:

student$ pg_probackup show \
  -B /var/probackup \
  --archive
ARCHIVE INSTANCE 'ent-16'
==========================================================================================
=======
 TLI  Parent TLI  Switchpoint  Min Segno  Max Segno  N segments  Size  Zratio  N backups
Status
==========================================================================================
=======

Пока он пуст. Переключим сегмент WAL.

=> SELECT pg_switch_wal();
 pg_switch_wal
---------------
 0/15004FE4
(1 row)
=> INSERT INTO t1 VALUES ('Архивация WAL работает.');
INSERT 0 1

Сегмент WAL попал в архив:

student$ pg_probackup show \
  -B /var/probackup \
  --archive
ARCHIVE INSTANCE 'ent-16'
==========================================================================================
=====================================
 TLI  Parent TLI  Switchpoint  Min Segno                 Max Segno                 N
segments  Size  Zratio  N backups  Status
==========================================================================================
=====================================
 1    0           0/0          000000010000000000000015  000000010000000000000015  1
     16MB  1,00    1          OK

Выполним полное резервное копирование. Поскольку настроена файловая архивация, копировать WAL не нужно, ключ – stream не указываем.

student$ pg_probackup backup \

Page 16: Page 16

  -B /var/probackup --instance ent-16 \
  -b FULL

Проверим каталог резервных копий:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
======================================================
 Instance  Version  ID      Recovery Time                  Mode  WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN   Stop LSN    Status
==========================================================================================
======================================================
 ent-16    16       TIUPXO  2026-07-27 23:51:32.411384+03  FULL  ARCHIVE   1/0   40s
335MB  16MB  none    1,00  0/17000028  0/180000C0  OK
 ent-16    16       TIUPTT  2026-07-27 23:49:12.963247+03  FULL  STREAM    1/0   22s
335MB  16MB  none    1,00  0/10000028  0/100003C0  OK

Создадим еще одну таблицу.

=> CREATE TABLE t2 AS SELECT 'Проверка режима PAGE.' msg;
SELECT 1

Увеличим счетчик транзакций и запомним номер, он потребуется нам позже.

=> SELECT pg_current_xact_id();
 pg_current_xact_id
--------------------
                971
(1 row)

Предположим, что оператор по ошибке удалил таблицу t1:

=> DROP TABLE t1;
DROP TABLE

Выполним инкрементальное резервное копирование в режиме PAGE.

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b PAGE

Проверим каталог резервных копий:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
======================================================
 Instance  Version  ID      Recovery Time                  Mode  WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN   Stop LSN    Status
==========================================================================================
======================================================
 ent-16    16       TIUPYT  2026-07-27 23:52:08.698267+03  PAGE  ARCHIVE   1/1    5s
417kB  16MB  none    1,00  0/1A000028  0/1B0000C0  OK
 ent-16    16       TIUPXO  2026-07-27 23:51:32.411384+03  FULL  ARCHIVE   1/0   40s
335MB  16MB  none    1,00  0/17000028  0/180000C0  OK
 ent-16    16       TIUPTT  2026-07-27 23:49:12.963247+03  FULL  STREAM    1/0   22s
335MB  16MB  none    1,00  0/10000028  0/100003C0  OK

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

student$ sudo systemctl stop postgrespro-ent-16.service

Удаляем содержимое PGDATA:

student$ sudo rm -rf /var/lib/pgpro/ent-16/*

Восстанавливаем из цепочки копий:

student$ pg_probackup restore \
  -B /var/probackup \
  --instance ent-16 \
  --remote-user=postgres \
  --remote-host=localhost \
  --archive-host=localhost \
  --archive-user=student \
  -i TIUPYT

Запускаем экземпляр.

Page 17: Page 17

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2

Для восстановления использовалась такая команда получения сегментов из архива WAL:

=> SHOW restore_command;
restore_command
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
 "/opt/pgpro/ent-16/bin/pg_probackup" archive-get -B "/var/probackup" --instance "ent-16"
--wal-file-path=%p --wal-file-name=%f --remote-host=localhost --remote-user=student
(1 row)

Ее сформировала утилита по переданным ей archive-параметрам. Восстановление прошло успешно, но, естественно, таблица t2 по-прежнему на месте, а t1 — отсутствует:

=> SELECT * FROM t2;
          msg
-----------------------
 Проверка режима PAGE.
(1 row)
=> SELECT * FROM t1;
ERROR:  relation "t1" does not exist
LINE 1: SELECT * FROM t1;
                      ^

Page 18: Способы восстановления

Восстановление PITR

  • Частичное восстановление
  • Восстановление страниц
  • Синхронизация

Page 19: Восстановление PITR

Source slide page 19: Восстановление PITR{#source-figure-019 caption=“Source slide page 19: Восстановление PITR”}

При наличии архива WAL можно восстановить систему на момент времени — point-in-time recovery

  • Требуется архив WAL от момента создания резервной копии

Комментарии преподавателя

Если до выполнения резервного копирования уже был настроен архив WAL, то с помощью pg_probackup можно выполнить восстановление на момент времени в прошлом (Point-In-Time Recovery, PITR). Независимо от того, является ли резервная копия автономной (включает журнальные файлы) или нет, требуется наличие архива WAL как минимум с момента создания резервной копии.

При восстановлении на момент времени не обязательно указывать идентификатор копии. Утилита pg_probackup автоматически выберет резервную копию, ближайшую к заданной целевой точке, и начнет восстановление.

Указать точку восстановления можно параметрами:

● –recovery-target-time — на заданное время в формате timestamp;

● –recovery-target-xid — до заданной транзакции;

● –recovery-target-lsn — до заданного LSN;

● –recovery-target-name — до заранее созданной именованной точки;

● –recovery-target=‘latest’ — до последнего согласованного состояния;

● –recovery-target=‘immediate’ — до самого раннего согласованного состояния.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-PERFORM ING-POINT-IN-TIME-PITR-RECOVERY

Page 20: Восстановление PITR

Итак, мы обнаружили, что таблица была удалена, и решили восстановить данные на момент до удаления таблицы. Ранее мы выяснили номер транзакции — 971. Восстановим данные до этого номера.

student$ sudo systemctl stop postgrespro-ent-16.service
student$ sudo rm -rf /var/lib/pgpro/ent-16/*

Восстанавливаемся, используя цепочку копий, до XID 971:

student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  --log-level-console=INFO \
  --recovery-target-xid=971 \
  --remote-user=postgres \
  --remote-host=localhost \
  --archive-host=localhost \
  --archive-user=student
INFO: Validating backup TIUPXO
INFO: validate_tablespace_map_content start
INFO: Backup TIUPXO data files are valid
INFO: Backup validation completed successfully on time 2026-07-27 23:52:04.749237+03, xid
971 and LSN 0/190103B0
INFO: Backup TIUPXO is valid.
INFO: Restoring the database from backup TIUPXO on localhost
INFO: Start restoring backup files. PGDATA size: 335MB
INFO: Backup files are restored. Transferred bytes: 335MB, time elapsed: 6s
INFO: Restore incremental ratio (less is better): 100% (335MB/335MB)
INFO: Syncing restored files to disk
INFO: Restored backup files are synced, time elapsed: 30s
INFO: Restore of backup TIUPXO completed.

Запускаем экземпляр.

student$ sudo systemctl start postgrespro-ent-16.service

При запуске сервер вошел в режим восстановления и применяет журнальные записи, пока не достигнет цели восстановления.

student$ psql pgpro_probackup_2

Проверим, восстановились ли уже таблицы (если нет, нужно подождать):

=> SELECT * FROM t1;
            msg
----------------------------
 Полная копия создана.
 Теперь сделаем разностную.
 Проверим PTRACK.
 Архивация WAL работает.
(4 rows)
=> SELECT * FROM t2;
          msg
-----------------------
 Проверка режима PAGE.
(1 row)

Поскольку цель — момент времени в прошлом, сервер останется в режиме восстановления:

=> SELECT pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 t
(1 row)

Переведем сервер в обычный режим.

=> SELECT pg_promote();

Page 21: Page 21

 pg_promote
------------
 t
(1 row)

Резервные копии, использующие архив WAL, больше не нужны. Удалим их.

student$ pg_probackup delete \
  -B /var/probackup --instance ent-16 \
  -i TIUPXO

Page 22: Частичное восстановление

Source slide page 22: Частичное восстановление{#source-figure-022 caption=“Source slide page 22: Частичное восстановление”}

Восстановление только требуемых баз данных кластера

  • -db-include — база данных для восстановления
  • -db-exclude — база данных, которую не надо восстанавливать

Комментарии преподавателя

Частичное восстановление применяется в случаях, когда не требуется восстанавливать все базы данных кластера.

Параметром –db-include можно задать имя базы данных для восстановления. Базы template0 и template1 восстанавливаются всегда. Можно указать несколько таких параметров, по одному для каждой восстанавливаемой базы данных.

Используя параметр –db-exclude, можно попросить утилиту восстановить все базы, кроме указанных.

Все файлы пропущенных баз данных все равно создаются утилитой, но создаются пустыми. Это необходимо, поскольку при старте экземпляра процесс startup проигрывает журнальные записи (как минимум для восстановления согласованности) и ожидает обнаружить соответствующие файлы данных. Затем ненужные базы данных можно удалить.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-PARTIAL-RESTORE

Page 23: Частичное восстановление

Восстановим из единственной оставшейся полной копии все базы данных кластера, кроме pgpro_probackup_2_bis.

student$ pg_probackup show \
   -B /var/probackup --instance ent-16
==========================================================================================
======================================================
 Instance  Version  ID      Recovery Time                  Mode  WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN   Stop LSN    Status
==========================================================================================
======================================================
 ent-16    16       TIUPTT  2026-07-27 23:49:12.963247+03  FULL  STREAM    1/0   22s
335MB  16MB  none    1,00  0/10000028  0/100003C0  OK

Останавливаем экземпляр.

student$ sudo systemctl stop postgrespro-ent-16.service

Удаляем содержимое PGDATA:

student$ sudo rm -rf /var/lib/pgpro/ent-16/*

Добавим к командной строке параметр –db-exclude, чтобы база pgpro_probackup_2_bis не восстанавливалась:

student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  --remote-user=postgres \
  --remote-host=localhost \
  --archive-host=localhost \
  --archive-user=student \
  --db-exclude=pgpro_probackup_2_bis \
  -i TIUPTT

Запускаем экземпляр.

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2

База данных pgpro_probackup_2_bis есть в списке:

=> \l
                                                             List of databases
         Name          |  Owner   | Encoding | Locale Provider |   Collate   |    Ctype
 | ICU Locale | ICU Rules |   Access privileges
-----------------------+----------+----------+-----------------+-------------+------------
-+------------+-----------+-----------------------
 demo                  | student  | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           |
 pgpro_probackup_2     | backup   | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           |
 pgpro_probackup_2_bis | student  | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           |
 postgres              | postgres | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           |
 student               | postgres | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           |
 template0             | postgres | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           | =c/postgres          +
                       |          |          |                 |             |
 |            |           | postgres=CTc/postgres
 template1             | postgres | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           | =c/postgres          +
                       |          |          |                 |             |
 |            |           | postgres=CTc/postgres
 templateprobackup     | postgres | UTF8     | icu             | en_US.UTF-8 |
en_US.UTF-8 | en-US      |           |
(8 rows)

Однако подключиться к ней нельзя:

student$ psql pgpro_probackup_2_bis
psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL:
"base/24733" is not a valid data directory

Page 24: Page 24

DETAIL:  File "base/24733/PG_VERSION" does not contain valid data.
HINT:  You might need to initdb.

В подкаталоге PGDATA этой базы только пустые файлы:

student$ sudo ls -l /var/lib/pgpro/ent-16/base/24733 | tail
-rw-r----- 1 postgres postgres 0 июл 27 23:54 827
-rw-r----- 1 postgres postgres 0 июл 27 23:54 828
-rw-r----- 1 postgres postgres 0 июл 27 23:54 9001
-rw-r----- 1 postgres postgres 0 июл 27 23:54 9002
-rw-r----- 1 postgres postgres 0 июл 27 23:54 9003
-rw-r----- 1 postgres postgres 0 июл 27 23:54 9004
-rw-r----- 1 postgres postgres 0 июл 27 23:54 9040
-rw-r----- 1 postgres postgres 0 июл 27 23:54 9041
-rw-r----- 1 postgres postgres 0 июл 27 23:54 pg_filenode.map
-rw-r----- 1 postgres postgres 0 июл 27 23:54 PG_VERSION

Эту базу данных можно удалить из системного каталога, файлы при этом тоже удалятся.

=> DROP DATABASE pgpro_probackup_2_bis;
DROP DATABASE
student$ sudo ls -l /var/lib/pgpro/ent-16/base/24733
ls: cannot access '/var/lib/pgpro/ent-16/base/24733': No such file or directory

Целостность восстановленных баз данных можно проверить командой checkdb:

student$ pg_probackup checkdb \
  -B /var/probackup --instance ent-16 \
  --remote-user=postgres \
  --remote-host=localhost \
  -d pgpro_probackup_2

Теперь можно работать с восстановленными данными:

=> \c pgpro_probackup_2
You are now connected to database "pgpro_probackup_2" as user "student".
=> INSERT INTO t1 VALUES ('После частичного восстановления.');
INSERT 0 1
=> SELECT * FROM t1;
               msg
----------------------------------
 Полная копия создана.
 Теперь сделаем разностную.
 После частичного восстановления.
(3 rows)

Page 25: Восстановление страниц

Source slide page 25: Восстановление страниц{#source-figure-025 caption=“Source slide page 25: Восстановление страниц”}

CHECKSUM

  • восстановление испорченных страниц и страниц,
  • отличающихся от резервной копии

Комментарии преподавателя

При инкрементальном восстановлении (восстановлении страниц) каталог данных экземпляра не перезаписывается полностью, а только обновляется теми страницами, состояние которых изменилось по сравнению с резервной копией. Если каталог данных не сильно отличается от копии, такое восстановление будет работать значительно быстрее обычного.

Для инкрементального восстановления в командную строку добавляется параметр -I, после которого указывается один из двух режимов: CHECKSUM или LSN. Эти режимы определяют, как именно будут выбираться страницы, требующие восстановления.

В режиме CHECKSUM восстанавливаются страницы с некорректной контрольной суммой или с номером LSN, отличающимся от LSN в резервной копии. Для этого утилита читает все файлы данных экземпляра, получает их контрольные суммы и LSN, а затем сравнивает эту информацию с содержимым резервной копии. Если имеет место цепочка инкрементальных резервных копий, в более ранних копиях ищутся только те страницы, которые не были найдены в более поздних.

Экономия достигается за счет того, что только изменившиеся страницы передаются по сети и записываются на диск целевого экземпляра.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-INCREME NTAL-RESTORE

Page 26: Восстановление страниц

Source slide page 26: Восстановление страниц{#source-figure-026 caption=“Source slide page 26: Восстановление страниц”}

LSN

  • восстановление испорченных страниц и страниц,
  • измененных после точки сдвига
  • точка сдвига — наиболее поздняя копия из инкрементальной цепочки,
  • соответствующая прошлому состоянию каталога данных экземпляра

Комментарии преподавателя

В режиме LSN утилита пытается найти в инкрементальной цепочке целевой резервной копии наиболее позднюю копию, соответствующую какому-либо состоянию каталога данных экземпляра в прошлом. Момент завершения создания этой копии называется точкой сдвига (Shift LSN) и принадлежит некоторой линии времени. Точка сдвига важна тем, что страницы экземпляра с LSN ≤ Shift LSN заведомо совпадают со страницами, которые можно восстановить из целевой резервной копии, то есть при восстановлении такие страницы можно просто игнорировать.

Если подходящей на роль точки сдвига копии нет, восстановление в режиме LSN невозможно (режим CHECKSUM доступен всегда).

На слайде копия Δ2 не может служить точкой сдвига, поскольку не соответствует никакому прошлому состоянию экземпляра: она была сделана в первой линии времени, а экземпляр в некоторый момент переключился на вторую линию. А копия Δ1 удовлетворяет условиям и будет выбрана в качестве точки сдвига.

Режим LSN требует корректности файла pg_control, поскольку из него считывается Redo LSN и линия времени экземпляра, и наличия необходимых файлов истории в архиве WAL. Также должны быть включены контрольный суммы.

Однако если режим доступен, он оказывается более эффективным, чем CHECKSUM. Файлы каталога данных все равно читаются полностью, но в режиме CHECKSUM по резервной копии проверяются все страницы, а в LSN — только измененные позже точки сдвига.

Page 27: Восстановление страниц (инкрементальное)

student$ sudo systemctl stop postgrespro-ent-16.service

В предыдущем опыте частичного восстановления база данных pgpro_probackup_2_bis не была восстановлена. Инкрементальное восстановление позволит не копировать лишние данные, ограничившись только недостающими и измененными страницами. В управляющем файле кластера есть информация о последней контрольной точке, которая определяет текущее положение экземпляра на линии времени:

student$ /opt/pgpro/ent-16/bin//pg_controldata -D /var/lib/pgpro/ent-16 \
| grep -e ' TimeLineID' -e ' REDO location'
Latest checkpoint's REDO location:    0/11000A68
Latest checkpoint's TimeLineID:       1

В хранилище резервных копий хранится информация о линии времени и LSN завершения создания копии:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT \
  | grep -e stop-lsn -e timeline
timelineid = 1
stop-lsn = 0/100003C0

В нашем случае линия времени всего одна, а имеющаяся копия отражает прошлое состояние экземпляра, так что может служить точкой сдвига для режима LSN (Backup TIUPTT is chosen as shiftpoint):

student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT \
  -I LSN \
  --log-level-console=INFO \
  --remote-user=postgres \
  --remote-host=localhost
INFO: Running incremental restore into nonempty directory: "/var/lib/pgpro/ent-16"
INFO: Backup TIUPTT is chosen as shiftpoint, its Stop LSN will be used as shift LSN
INFO: Destination directory redo point 0/11000A68 on tli 1 is within reach of backup
TIUPTT with Stop LSN 0/100003C0 on tli 1
INFO: shift LSN: 0/100003C0
INFO: Validating backup TIUPTT
INFO: validate_tablespace_map_content start
INFO: Backup TIUPTT data files are valid
INFO: Backup TIUPTT WAL segments are valid
INFO: Backup TIUPTT is valid.
INFO: Restoring the database from backup TIUPTT on localhost
INFO: Extracting the content of destination directory for incremental restore
INFO: Destination directory content extracted, time elapsed: 0
INFO: Removing redundant files in destination directory
INFO: Redundant files are removed, time elapsed: 1s
INFO: Start restoring backup files. PGDATA size: 343MB
INFO: Backup files are restored. Transferred bytes: 24MB, time elapsed: 3s
INFO: Restore incremental ratio (less is better): 7% (24MB/343MB)
INFO: Syncing restored files to disk
INFO: Restored backup files are synced, time elapsed: 20s
INFO: Restore of backup TIUPTT completed.

Обратите внимание на строку «Restore incremental ratio (less is better)». Это отношение объема восстановленных страниц к общему объему данных в кластере. Чем меньше это значение, тем выше эффективность и скорость инкрементального восстановления.

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2

База данных pgpro_probackup_2_bis восстановлена.

=> \c pgpro_probackup_2_bis
You are now connected to database "pgpro_probackup_2_bis" as user "student".
=> SELECT current_catalog;

Page 28: Page 28

    current_catalog
-----------------------
 pgpro_probackup_2_bis
(1 row)

Page 29: Синхронизация

Source slide page 29: Синхронизация{#source-figure-029 caption=“Source slide page 29: Синхронизация”}

Копирование данных из одного экземпляра в другой

  • синхронизация отставшего ведомого сервера с ведущим
  • добавление нового ведомого сервера

Комментарии преподавателя

Быстро клонировать экземпляр или синхронизировать отставшую реплику позволяет команда catchup утилиты pg_probackup. Она не использует каталог резервных копий, а берет данные непосредственно из каталога данных копируемого экземпляра.

Ускорение относительно обычных средств может достигаться за счет:

● многопоточной передачи данных;

● инкрементального копирования (с дополнению к режиму FULL доступны DELTA и PTRACK).

Использование команды catchup для синхронизации отставшей реплики позволяет избежать сложных ручных процедур с использованием rsync и подобных инструментов.

Команда catchup отличается от других операций, выполняемых утилитой pg_probackup:

● по умолчанию конфигурационные файлы целевого сервера заменяются файлами исходного сервера;

● возможна только потоковая доставка WAL (архив не используется);

● не копируются внешние каталоги;

● запрещено одновременное выполнение команд DDL, создающих или удаляющих табличные пространства.

https://postgrespro.ru/docs/enterprise/16/app-pgprobackup#PBK-CREATIN G-BACKUP-TO-CATCHUP

Page 30: Синхронизация

Создадим физическую реплику с помощью утилиты pg_probackup, восстановив данные из резервной копии двумя потоками:

student$ sudo rm -rf /var/lib/pgpro/ent-16-prod
student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  -D /var/lib/pgpro/ent-16-prod \
  -i TIUPTT \
  -j 2 \
  --allow-group-access \
  --restore-as-replica \
  --remote-user=postgres \
  --remote-host=localhost

Здесь были использованы следующие параметры командной строки pg_probackup: -D — целевой каталог для восстановления; -j — копировать в несколько потоков; –restore-as-replica — создать файл standby.signal и настроить строку подключения к мастеру. Запустим реплику, изменив перед этим номер порта в конфигурации.

/var/lib/pgpro/ent-16-prod/postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
# recovery settings added by pg_probackup restore of backup TIUPSI at '2026-07-27
23:48:24+03'
# recovery settings added by pg_probackup restore of backup TIUPTT at '2026-07-27
23:55:48+03'
## standby settings
primary_conninfo = 'user=backup reusepass=1 channel_binding=prefer host=localhost
port=5432 sslmode=prefer sslcompression=0 sslcertmode=allow sslsni=1
ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres gssdelegation=0
target_session_attrs=any target_server_type=any hostorder=sequential
load_balance_hosts=disable'
port = 5434
postgres$ /opt/pgpro/ent-16/bin/pg_ctl \
  -w \
  -D /var/lib/pgpro/ent-16-prod \
  -l /var/lib/pgpro/ent-16-prod/pgpro-ent.log \
  start
waiting for server to start...................... done
server started

Проверим работу репликации.

=> \c pgpro_probackup_2
You are now connected to database "pgpro_probackup_2" as user "student".
=> TRUNCATE t1;
TRUNCATE TABLE
=> INSERT INTO t1 SELECT 'string #' || g.i AS msg FROM generate_series(1, 1_000_000) AS g(i);
INSERT 0 1000000

Репликация работает:

student$ psql -p 5434
=> \c pgpro_probackup_2
You are now connected to database "pgpro_probackup_2" as user "student".
=> SELECT pg_is_in_recovery();

Page 31: Page 31

 pg_is_in_recovery
-------------------
 t
(1 row)
=> SELECT count(*) FROM t1;
  count
---------
 1000000
(1 row)

На реплике аварийно завершается основной процесс:

student$ sudo kill -QUIT $(sudo head -n 1 /var/lib/pgpro/ent-16-prod/postmaster.pid)

Пока реплика простаивает, на основном сервере изменим тысячу строк:

=> UPDATE t1 SET msg = msg || '!' WHERE msg ~ '000$';
UPDATE 1000

Если реплика долго простаивала, ее синхронизации может занять долгое время, даже если все нужные журнальные файлы еще сохранились на основном сервере. Мы хотим ускорить синхронизацию, передав данные с мастера на реплику командой catchup, которая будет передавать только измененные страницы. Используем режим инкрементального копирования DELTA, укажем пути к каталогам данных. Дополнительный файл конфигурации не копируем:

postgres$ /opt/pgpro/ent-16/bin/pg_probackup catchup \
  -b DELTA \
  --threads=2 \
  --source-pgdata=/var/lib/pgpro/ent-16 \
  --destination-pgdata=/var/lib/pgpro/ent-16-prod \
  --exclude-path=postgresql.auto.conf \
  --log-level-console=INFO \
  -U backup \
  -d pgpro_probackup_2
INFO: --stream is required, forcing stream mode
INFO: This PostgreSQL instance was initialized with data block checksums. Data block
corruption will be detected
INFO: Catchup start, pg_probackup version: 2.8.14, PostgreSQL version: 16, remote: false,
source-pgdata: /var/lib/pgpro/ent-16, destination-pgdata: /var/lib/pgpro/ent-16-prod
INFO: Database catchup start
INFO: Destination file "/var/lib/pgpro/ent-16-prod/postgresql.auto.conf" excluded with
--exclude-path option
INFO: syncLSN = 0/10000028
INFO: Enable CFS flock feature
INFO: wait for pg_backup_start()
INFO: pg_start_backup START LSN 0/16000028
INFO: Source file "/var/lib/pgpro/ent-16/postgresql.auto.conf" excluded with
--exclude-path option
INFO: Source PGDATA size: 377MB (excluded 280B)
INFO: Start LSN (source): 0/16000028, TLI: 1
INFO: LSN in destination: 0/10000028, TLI: 1
INFO: Removing redundant files in destination directory
WARNING: Renaming pg_control file: Cannot rename file
"/var/lib/pgpro/ent-16-prod/global/pg_control" to
"/var/lib/pgpro/ent-16-prod/global/pg_control.pbk.bak": No such file or directory
INFO: Start transferring data files
INFO: wait for pg_stop_backup()
INFO: pg_stop_backup() successfully executed
INFO: stop_stream_lsn 0/16920000 currentpos 0/16920000
INFO: Databases synchronized. Transferred datafiles size: 10232kB, transferred wal size:
16MB, time elapsed: 1s
INFO: Catchup incremental ratio (less is better): 3% (10232kB/377MB)
INFO: Syncing copied files to disk
INFO: Files are synced, time elapsed: 18s

Обратите внимание на строку «Catchup incremental ratio (less is better)» — она показывает отношение объема переданных для синхронизации страниц к их общему объему. Чем меньше значение, тем эффективнее работает синхронизация. Запустим реплику.

postgres$ /opt/pgpro/ent-16/bin/pg_ctl \
  -w \
  -D /var/lib/pgpro/ent-16-prod \
  -l /var/lib/pgpro/ent-16-prod/pgpro-ent.log \
  start

Page 32: Page 32

waiting for server to start..................... done
server started
student$ psql -p 5434 pgpro_probackup_2

Проверим данные на реплике:

=> SELECT count(*) FROM t1 WHERE msg ~ '!$';
 count
-------
  1000
(1 row)

Все измененные строки синхронизированы.

Page 33: Итоги

Утилита pg\_probackup поддерживает инкрементальное копирование и инкрементальное восстановление измененных страниц

  • При наличии архива WAL поддерживается восстановление на момент в прошлом
  • Возможно восстановление части данных кластера и эффективная синхронизация двух кластеров

Page 34: Практика

  1. Подготовьте экземпляр к работе с архивированием WAL, создайте базу данных, выполните полное копирование со сжатием. 2. Измените какие-либо данные в базе и выполните инкрементальное страничное копирование со сжатием. 3. Убедитесь, что полученная цепочка копий пригодна для восстановления экземпляра. 4. Имитируйте аварию сервера с физической порчей данных. 5. Восстановите испорченные данные, не затрагивая при этом другие данные кластера.

Комментарии преподавателя

  1. Аварийно завершите основной процесс экземпляра. Измените файл основного слоя таблицы средствами ОС, например:
dd if=/dev/urandom of=файл conv=fdatasync bs=8K count=10
  1. Выполните инкрементальное восстановление в режиме CHECKSUM.

Page 35: 1. Подготовка каталога резервных копий и регистрация экземпляра. Режим WAL

Создадим и подготовим каталог копий.

student$ sudo mkdir /var/probackup
student$ sudo chown student: /var/probackup

Инициализируем каталог.

student$ pg_probackup init -B /var/probackup
INFO: Backup catalog '/var/probackup' successfully initialized

Регистрируем экземпляр.

student$ pg_probackup add-instance \
  -B /var/probackup --instance ent-16 \
  -D /var/lib/pgpro/ent-16 \
  --remote-host=localhost \
  --remote-user=postgres
INFO: Instance 'ent-16' successfully initialized

Создадим базу данных.

=> CREATE DATABASE pgpro_probackup_2 OWNER backup TEMPLATE templateprobackup;
CREATE DATABASE
student$ psql
=> \c pgpro_probackup_2
You are now connected to database "pgpro_probackup_2" as user "student".

Запомним в настройках конфигурации атрибуты подключения.

student$ pg_probackup set-config \
  -B /var/probackup --instance ent-16 \
  -d pgpro_probackup_2 -U backup \
  --remote-host=localhost \
  --remote-user=postgres \
  --log-level-console=ERROR

Подготовимся к работе в режиме архивирования WAL.

=> ALTER SYSTEM SET archive_mode = on;
ALTER SYSTEM
=> ALTER SYSTEM SET archive_command =
' /opt/pgpro/ent-16/bin/pg_probackup archive-push'
' -B /var/probackup --instance=ent-16'
' --wal-file-path=%p'
' --wal-file-name=%f'
' --remote-host=localhost'
' --remote-user=student'
' --compress';
ALTER SYSTEM

Перезапустим сервер:

student$ sudo systemctl restart postgrespro-ent-16.service
student$ psql pgpro_probackup_2

Проверим работу архивирования WAL.

=> SELECT pg_switch_wal();
 pg_switch_wal
---------------
 0/BF4DC8C
(1 row)
=> CREATE TABLE t AS SELECT 'Тест архивирования WAL.' msg;
SELECT 1

Page 36: Page 36

Проверим, попал ли сегмент WAL в архив.

student$ pg_probackup show \
  -B /var/probackup \
  --archive
ARCHIVE INSTANCE 'ent-16'
==========================================================================================
=======================================
 TLI  Parent TLI  Switchpoint  Min Segno                 Max Segno                 N
segments  Size    Zratio  N backups  Status
==========================================================================================
=======================================
 1    0           0/0          00000001000000000000000B  00000001000000000000000B  1
     5329kB  3,07    0          OK

Получим список сжатых сегментов WAL, помещенных в архив:

student$ ls -R /var/probackup/wal/ent-16
/var/probackup/wal/ent-16:
00000001000000000000000B.zst

По умолчанию сжатие производится методом zstd. Теперь сделаем полную резервную копию со сжатием.

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  --compress \
  -b FULL

2. Инкрементальная копия

Добавим строку в таблицу.

=> INSERT INTO t VALUES('Еще одна строка.');
INSERT 0 1

Сформируем инкрементальную копию, тоже со сжатием.

student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  --compress \
  -b PAGE

Содержимое каталога копий:

student$ pg_probackup show \
  -B /var/probackup --instance ent-16
==========================================================================================
======================================================
 Instance  Version  ID      Recovery Time                  Mode  WAL Mode  TLI  Time
Data   WAL  Zalg  Zratio  Start LSN   Stop LSN    Status
==========================================================================================
======================================================
 ent-16    16       TIUR8G  2026-07-28 00:19:30.503253+03  PAGE  ARCHIVE   1/1    3s
170kB  16MB  zstd    1,20  0/10000028  0/110000C0  OK
 ent-16    16       TIUR7F  2026-07-28 00:18:57.387743+03  FULL  ARCHIVE   1/0   35s
83MB  16MB  zstd    3,93  0/D000028   0/E0016F8   OK

3. Восстановление из сжатой резервной копии

Остановим экземпляр.

student$ sudo systemctl stop postgrespro-ent-16.service

Удалим содержимое PGDATA.

student$ sudo rm -rf /var/lib/pgpro/ent-16/*

Восстановим экземпляр из цепочки резервных копий.

student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  -i TIUR8G \
  --archive-host=localhost \
  --archive-user=student

Page 37: Page 37

Запустим экземпляр.

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2
=> SELECT * FROM t;
           msg
-------------------------
 Тест архивирования WAL.
 Еще одна строка.
(2 rows)

Данные восстановлены.

4. Авария сервера

Определим физический путь к файлу, содержащему страницы таблицы t.

=> SELECT pg_relation_filepath('t');
 pg_relation_filepath
----------------------
 base/16541/16542
(1 row)

На сервере происходит авария.

student$ sudo kill -QUIT $(sudo head -n 1 /var/lib/pgpro/ent-16/postmaster.pid)

Сымитируем физическую порчу файла данных, записав в него 10 страниц (80 килобайт) случайных данных:

postgres$ dd if=/dev/urandom of=/var/lib/pgpro/ent-16/base/16541/16542 conv=fdatasync bs=8K count=10
10+0 records in
10+0 records out
81920 bytes (82 kB, 80 KiB) copied, 0,132144 s, 620 kB/s

Запустим сервер.

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2

Попытаемся обратиться к таблице.

=> SELECT * FROM t;
WARNING:  page verification failed, calculated checksum 6184 but expected 30746
ERROR:  invalid page in block 1 of relation base/16541/16542

5. Инкрементальное восстановление таблицы

Мы хотим восстановить испорченные страницы, не копируя при этом остальные данные кластера. Остановим сервер.

student$ sudo systemctl stop postgrespro-ent-16.service

Выполним инкрементальное восстановление в режиме CHECKSUM.

student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  --log-level-console=INFO \
  -I CHECKSUM \
  --remote-user=postgres \
  --remote-host=localhost \
  --archive-host=localhost \
  --archive-user=student
INFO: Running incremental restore into nonempty directory: "/var/lib/pgpro/ent-16"
INFO: Validating parents for backup TIUR8G
INFO: Validating backup TIUR7F
INFO: validate_tablespace_map_content start
INFO: Backup TIUR7F data files are valid
INFO: Validating backup TIUR8G
INFO: validate_tablespace_map_content start
INFO: Backup TIUR8G data files are valid
INFO: Backup TIUR8G WAL segments are valid

Page 38: Page 38

INFO: Backup TIUR8G is valid.
INFO: Restoring the database from backup TIUR8G on localhost
INFO: Extracting the content of destination directory for incremental restore
INFO: Destination directory content extracted, time elapsed: 0
INFO: Removing redundant files in destination directory
INFO: Redundant files are removed, time elapsed: 0
INFO: Start restoring backup files. PGDATA size: 327MB
INFO: Backup files are restored. Transferred bytes: 1357kB, time elapsed: 4s
INFO: Restore incremental ratio (less is better): 0% (1357kB/327MB)
INFO: Syncing restored files to disk
INFO: Restored backup files are synced, time elapsed: 16s
INFO: Restore of backup TIUR8G completed.

Был скопирован примерно 1 мегабайт данных при общем объеме кластера около 300 мегабайт. Запустим сервер.

student$ sudo systemctl start postgrespro-ent-16.service
student$ psql pgpro_probackup_2

Таблица восстановлена:

=> SELECT * FROM t;
           msg
-------------------------
 Тест архивирования WAL.
 Еще одна строка.
(2 rows)

Уборка

Удалим созданную базу данных и каталог копий, сбросим настройки параметров конфигурации.

=> \c student
You are now connected to database "student" as user "student".
=> DROP DATABASE pgpro_probackup_2 WITH (FORCE);
DROP DATABASE
student$ sudo rm -rf /var/probackup
=> ALTER SYSTEM RESET ALL;
ALTER SYSTEM
student$ sudo systemctl restart postgrespro-ent-16.service