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

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

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

<!-- Generated by scripts/generate_skeleton.py. -->

> [!NOTE]
> Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета.
> **HTML source:** [pgpro_19_probackup_2.html](https://edu.postgrespro.ru/16/pgpro-16/pgpro_19_probackup_2.html)
> **Archive:** [PGPRO-handouts-16.zip](https://edu.postgrespro.ru/16/PGPRO-handouts-16.zip)
> **Страниц PDF:** 38

## Page 1: Резервное копирование / Использование pg_probackup {#source-page-001}

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

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

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

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

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

## Page 2: Темы {#source-page-002}

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

## Page 3: Инкрементальные копии {#source-page-003}

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

## Page 4: Копирование DELTA {#source-page-004}

![Source slide page 4: Копирование DELTA](images/page-004.png){#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-page-005}

![Source slide page 5: Восстановление](images/page-005.png){#source-figure-005 caption="Source slide page 5: Восстановление"}

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

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

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

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

## Page 6: Копирование DELTA {#source-page-006}

Создадим базу данных, к которой будет подключаться роль backup.
```sql
=> CREATE DATABASE pgpro_probackup_2 OWNER backup TEMPLATE templateprobackup;
```
```sql
CREATE DATABASE
```
```sql
=> \c pgpro_probackup_2
```
```text
You are now connected to database "pgpro_probackup_2" as user "student".
```
Мы будем запускать утилиту локально от имени пользователя ОС student, а агент на удаленном сервере будет обращаться к файлам кластера от имени postgres. Необходимые настройки в виртуальной машине курса уже произведены.
Подготовим локальный каталог копий, владелец файлов — student.
```sh
student$ sudo mkdir /var/probackup
```
```sh
student$ sudo chown student: /var/probackup
```
```sh
student$ pg_probackup init \
  -B /var/probackup
```
```text
INFO: Backup catalog '/var/probackup' successfully initialized
```
Добавим в локальный каталог копий экземпляр БД, работающий на целевом сервере.
```sh
student$ pg_probackup add-instance \
  -B /var/probackup --instance ent-16 \
  -D /var/lib/pgpro/ent-16 \
  --remote-host=localhost \
  --remote-user=postgres
```
```text
INFO: Instance 'ent-16' successfully initialized
```
Не забудем о настройках конфигурации:
```sh
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:
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b FULL \
  --stream
```
В каталоге резервных копий появилась запись:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
====================================================
 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
```
Произведем какие-нибудь изменения, например, создадим таблицу:
```sql
=> CREATE TABLE IF NOT EXISTS t1 (
  msg text
);
```
```sql
CREATE TABLE
```

## Page 7: Page 7 {#source-page-007}

И запишем в нее данные:
```sql
=> INSERT INTO t1 VALUES ('Полная копия создана.'), ('Теперь сделаем разностную.');
```
```sql
INSERT 0 2
```
Получим разностную резервную копию:
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b DELTA --stream
```
Что теперь в каталоге копий?
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
======================================================
 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
```
Обратите внимание, насколько разностная копия меньше полной.
Восстановим кластер из последней копии. Остановим экземпляр:
```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
Удалим содержимое PGDATA.
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16/*
```
При восстановлении указываем разностную копию:
```sh
student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  -i TIUPSI
```
Запускаем экземпляр.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
```sql
=> SELECT * FROM t1;
```
```text
            msg
----------------------------
 Полная копия создана.
 Теперь сделаем разностную.
(2 rows)
```
Мы восстановили данные, использовав цепочку из полной и разностной копий.

## Page 8: Объединение копий {#source-page-008}

![Source slide page 8: Объединение копий](images/page-008.png){#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: Объединение копий {#source-page-009}

Еще раз изменим данные: создадим базу данных, которая нам понадобится в дальнейшем.
```sql
=> CREATE DATABASE pgpro_probackup_2_bis;
```
```sql
CREATE DATABASE
```
Получим вторую разностную резервную копию:
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b DELTA --stream
```
Состояние каталога копий:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
========================================================
 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
```
В информации о резервной копии есть номер родительской копии:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT | grep 'parent-backup-id'
```
```text
parent-backup-id = 'TIUPSI'
```
Третья копия, последняя в цепочке, содержит изменения данных, произошедшие после построения копии с этим идентификатором.
По мере добавления инкрементальных копий они будут занимать все больше дискового пространства. Можно выполнить полное копирование и удалить все предыдущие копии, но удобнее воспользоваться объединением копий.
```sh
student$ pg_probackup merge \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT
```
В результате имеем единственную полную копию, объединяющую в себе три предыдущие:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
======================================================
 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-page-010}

![Source slide page 10: Копирование PTRACK](images/page-010.png){#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 {#source-page-011}

Подключим библиотеку PTRACK к экземпляру.
```sql
=> ALTER SYSTEM SET shared_preload_libraries = 'ptrack';
```
```sql
ALTER SYSTEM
```
Экземпляр необходимо перезагрузить.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
Установим расширение в базу pgpro\_probackup\_2.
```sh
student$ psql pgpro_probackup_2
```
```sql
=> CREATE EXTENSION IF NOT EXISTS ptrack;
```
```sql
CREATE EXTENSION
```
Необходимо задать значение параметра ptrack.map\_size, рекомендуется 1/1024 объема кластера Postgres Pro:
```sql
=> ALTER SYSTEM SET ptrack.map_size = '1MB';
```
```sql
ALTER SYSTEM
```
Изменение этого параметра также требует перезапуска.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
Существующая полная копия была сделана до того, как PTRACK стал отслеживать изменения, поэтому для демонстрации работы PTRACK нам потребуется новая полная копия.
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b FULL \
  --allow-group-access \
  --stream
```
Добавим в таблицу еще одну строку.
```sh
student$ psql pgpro_probackup_2
```
```sql
=> INSERT INTO t1 VALUES ('Проверим PTRACK.');
```
```sql
INSERT 0 1
```
Теперь выполним инкрементальное резервное копирование в режиме PTRACK.
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b PTRACK \
  --allow-group-access \
  --stream
```
В каталоге резервных копий появилась инкрементальная копия:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
=========================================================
 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
```
Восстановление в данном случае производится так же, как и для разностных копий. Однако, какая копия будет использована для восстановления, если явно не указать идентификатор?
```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
Очистим каталог данных.
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16/*
```

## Page 12: Page 12 {#source-page-012}

Восстанавливаем кластер, не указывая идентификатор копии.
```sh
student$ pg_probackup restore \
  -B /var/probackup --instance ent-16
```
Запускаем экземпляр.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
```sql
=> SELECT * FROM t1;
```
```text
            msg
----------------------------
 Полная копия создана.
 Теперь сделаем разностную.
 Проверим PTRACK.
(3 rows)
```
Итак, была использована самая свежая копия.
Удалим эти копии, больше они не потребуются.
```sh
student$ pg_probackup delete \
  -B /var/probackup --instance ent-16 \
  -i TIUPV3
```
PTRACK тоже больше не нужен.
```sql
=> ALTER SYSTEM RESET ALL;
```
```sql
ALTER SYSTEM
```
```sql
=> DROP EXTENSION ptrack;
```
```sql
DROP EXTENSION
```
Мы перезапустим экземпляр позже.

## Page 13: Копирование PAGE {#source-page-013}

![Source slide page 13: Копирование PAGE](images/page-013.png){#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-page-014}

![Source slide page 14: Восстановление](images/page-014.png){#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 {#source-page-015}

Подготовим экземпляр к работе с архивацией WAL.
```sql
=> ALTER SYSTEM SET archive_mode = on;
```
```sql
ALTER SYSTEM
```
Для команды архивирования целевым является сервер резервного копирования, здесь ему соответствует localhost. Команда архивирования будет подключаться к серверу по SSH под именем владельца каталога резервных копий — пользователя student.
```sql
=> 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';
```
```sql
ALTER SYSTEM
```
Экземпляр необходимо перезапустить.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
Посмотрим содержимое архива WAL:
```sh
student$ pg_probackup show \
  -B /var/probackup \
  --archive
```
```text
ARCHIVE INSTANCE 'ent-16'
==========================================================================================
=======
 TLI  Parent TLI  Switchpoint  Min Segno  Max Segno  N segments  Size  Zratio  N backups
Status
==========================================================================================
=======
```
Пока он пуст.
Переключим сегмент WAL.
```sql
=> SELECT pg_switch_wal();
```
```text
 pg_switch_wal
---------------
 0/15004FE4
(1 row)
```
```sql
=> INSERT INTO t1 VALUES ('Архивация WAL работает.');
```
```sql
INSERT 0 1
```
Сегмент WAL попал в архив:
```sh
student$ pg_probackup show \
  -B /var/probackup \
  --archive
```
```text
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 не указываем.
```sh
student$ pg_probackup backup \
```

## Page 16: Page 16 {#source-page-016}

```text
  -B /var/probackup --instance ent-16 \
  -b FULL
```
Проверим каталог резервных копий:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
======================================================
 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
```
Создадим еще одну таблицу.
```sql
=> CREATE TABLE t2 AS SELECT 'Проверка режима PAGE.' msg;
```
```sql
SELECT 1
```
Увеличим счетчик транзакций и запомним номер, он потребуется нам позже.
```sql
=> SELECT pg_current_xact_id();
```
```text
 pg_current_xact_id
--------------------
                971
(1 row)
```
Предположим, что оператор по ошибке удалил таблицу t1:
```sql
=> DROP TABLE t1;
```
```sql
DROP TABLE
```
Выполним инкрементальное резервное копирование в режиме PAGE.
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  -b PAGE
```
Проверим каталог резервных копий:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
======================================================
 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
```
Сначала восстановим данные, используя инкрементальную копию. Останавливаем сервер:
```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
Удаляем содержимое PGDATA:
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16/*
```
Восстанавливаем из цепочки копий:
```sh
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 {#source-page-017}

```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
Для восстановления использовалась такая команда получения сегментов из архива WAL:
```text
=> SHOW restore_command;
```
```text
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 — отсутствует:
```sql
=> SELECT * FROM t2;
```
```text
          msg
-----------------------
 Проверка режима PAGE.
(1 row)
```
```sql
=> SELECT * FROM t1;
```
```sql
ERROR:  relation "t1" does not exist
LINE 1: SELECT * FROM t1;
                      ^
```

## Page 18: Способы восстановления {#source-page-018}

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

## Page 19: Восстановление PITR {#source-page-019}

![Source slide page 19: Восстановление PITR](images/page-019.png){#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 {#source-page-020}

Итак, мы обнаружили, что таблица была удалена, и решили восстановить данные на момент до удаления таблицы.
Ранее мы выяснили номер транзакции — 971. Восстановим данные до этого номера.
```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16/*
```
Восстанавливаемся, используя цепочку копий, до XID 971:
```sh
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
```
```sql
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.
```
Запускаем экземпляр.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
При запуске сервер вошел в режим восстановления и применяет журнальные записи, пока не достигнет цели восстановления.
```sh
student$ psql pgpro_probackup_2
```
Проверим, восстановились ли уже таблицы (если нет, нужно подождать):
```sql
=> SELECT * FROM t1;
```
```text
            msg
----------------------------
 Полная копия создана.
 Теперь сделаем разностную.
 Проверим PTRACK.
 Архивация WAL работает.
(4 rows)
```
```sql
=> SELECT * FROM t2;
```
```text
          msg
-----------------------
 Проверка режима PAGE.
(1 row)
```
Поскольку цель — момент времени в прошлом, сервер останется в режиме восстановления:
```sql
=> SELECT pg_is_in_recovery();
```
```text
 pg_is_in_recovery
-------------------
 t
(1 row)
```
Переведем сервер в обычный режим.
```sql
=> SELECT pg_promote();
```

## Page 21: Page 21 {#source-page-021}

```text
 pg_promote
------------
 t
(1 row)
```
Резервные копии, использующие архив WAL, больше не нужны. Удалим их.
```sh
student$ pg_probackup delete \
  -B /var/probackup --instance ent-16 \
  -i TIUPXO
```

## Page 22: Частичное восстановление {#source-page-022}

![Source slide page 22: Частичное восстановление](images/page-022.png){#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: Частичное восстановление {#source-page-023}

Восстановим из единственной оставшейся полной копии все базы данных кластера, кроме pgpro\_probackup\_2\_bis.
```sh
student$ pg_probackup show \
   -B /var/probackup --instance ent-16
```
```text
==========================================================================================
======================================================
 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
```
Останавливаем экземпляр.
```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
Удаляем содержимое PGDATA:
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16/*
```
Добавим к командной строке параметр --db-exclude, чтобы база pgpro\_probackup\_2\_bis не восстанавливалась:
```sh
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
```
Запускаем экземпляр.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
База данных pgpro\_probackup\_2\_bis есть в списке:
```text
=> \l
```
```text
                                                             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)
```
Однако подключиться к ней нельзя:
```sh
student$ psql pgpro_probackup_2_bis
```
```text
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 {#source-page-024}

```text
DETAIL:  File "base/24733/PG_VERSION" does not contain valid data.
HINT:  You might need to initdb.
```
В подкаталоге PGDATA этой базы только пустые файлы:
```sh
student$ sudo ls -l /var/lib/pgpro/ent-16/base/24733 | tail
```
```text
-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
```
Эту базу данных можно удалить из системного каталога, файлы при этом тоже удалятся.
```sql
=> DROP DATABASE pgpro_probackup_2_bis;
```
```sql
DROP DATABASE
```
```sh
student$ sudo ls -l /var/lib/pgpro/ent-16/base/24733
```
```text
ls: cannot access '/var/lib/pgpro/ent-16/base/24733': No such file or directory
```
Целостность восстановленных баз данных можно проверить командой checkdb:
```sh
student$ pg_probackup checkdb \
  -B /var/probackup --instance ent-16 \
  --remote-user=postgres \
  --remote-host=localhost \
  -d pgpro_probackup_2
```
Теперь можно работать с восстановленными данными:
```sql
=> \c pgpro_probackup_2
```
```text
You are now connected to database "pgpro_probackup_2" as user "student".
```
```sql
=> INSERT INTO t1 VALUES ('После частичного восстановления.');
```
```sql
INSERT 0 1
```
```sql
=> SELECT * FROM t1;
```
```text
               msg
----------------------------------
 Полная копия создана.
 Теперь сделаем разностную.
 После частичного восстановления.
(3 rows)
```

## Page 25: Восстановление страниц {#source-page-025}

![Source slide page 25: Восстановление страниц](images/page-025.png){#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-page-026}

![Source slide page 26: Восстановление страниц](images/page-026.png){#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: Восстановление страниц (инкрементальное) {#source-page-027}

```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
В предыдущем опыте частичного восстановления база данных pgpro\_probackup\_2\_bis не была восстановлена. Инкрементальное восстановление позволит не копировать лишние данные, ограничившись только недостающими и измененными страницами.
В управляющем файле кластера есть информация о последней контрольной точке, которая определяет текущее положение экземпляра на линии времени:
```sh
student$ /opt/pgpro/ent-16/bin//pg_controldata -D /var/lib/pgpro/ent-16 \
| grep -e ' TimeLineID' -e ' REDO location'
```
```text
Latest checkpoint's REDO location:    0/11000A68
Latest checkpoint's TimeLineID:       1
```
В хранилище резервных копий хранится информация о линии времени и LSN завершения создания копии:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT \
  | grep -e stop-lsn -e timeline
```
```text
timelineid = 1
stop-lsn = 0/100003C0
```
В нашем случае линия времени всего одна, а имеющаяся копия отражает прошлое состояние экземпляра, так что может служить точкой сдвига для режима LSN (Backup TIUPTT is chosen as shiftpoint):
```sh
student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  -i TIUPTT \
  -I LSN \
  --log-level-console=INFO \
  --remote-user=postgres \
  --remote-host=localhost
```
```sql
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)». Это отношение объема восстановленных страниц к общему объему данных в кластере. Чем меньше это значение, тем выше эффективность и скорость инкрементального восстановления.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
База данных pgpro\_probackup\_2\_bis восстановлена.
```sql
=> \c pgpro_probackup_2_bis
```
```text
You are now connected to database "pgpro_probackup_2_bis" as user "student".
```
```sql
=> SELECT current_catalog;
```

## Page 28: Page 28 {#source-page-028}

```text
    current_catalog
-----------------------
 pgpro_probackup_2_bis
(1 row)
```

## Page 29: Синхронизация {#source-page-029}

![Source slide page 29: Синхронизация](images/page-029.png){#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: Синхронизация {#source-page-030}

Создадим физическую реплику с помощью утилиты pg\_probackup, восстановив данные из резервной копии двумя потоками:
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16-prod
```
```sh
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 и настроить строку подключения к мастеру.
Запустим реплику, изменив перед этим номер порта в конфигурации.
```text
/var/lib/pgpro/ent-16-prod/postgresql.auto.conf
```
```sql
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
```
```text
# recovery settings added by pg_probackup restore of backup TIUPSI at '2026-07-27
23:48:24+03'
```
```text
# recovery settings added by pg_probackup restore of backup TIUPTT at '2026-07-27
23:55:48+03'
```
```text
## 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
```
```sh
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
```
```text
waiting for server to start...................... done
server started
```
Проверим работу репликации.
```sql
=> \c pgpro_probackup_2
```
```text
You are now connected to database "pgpro_probackup_2" as user "student".
```
```text
=> TRUNCATE t1;
```
```text
TRUNCATE TABLE
```
```sql
=> INSERT INTO t1 SELECT 'string #' || g.i AS msg FROM generate_series(1, 1_000_000) AS g(i);
```
```sql
INSERT 0 1000000
```
Репликация работает:
```sh
student$ psql -p 5434
```
```sql
=> \c pgpro_probackup_2
```
```text
You are now connected to database "pgpro_probackup_2" as user "student".
```
```sql
=> SELECT pg_is_in_recovery();
```

## Page 31: Page 31 {#source-page-031}

```text
 pg_is_in_recovery
-------------------
 t
(1 row)
```
```sql
=> SELECT count(*) FROM t1;
```
```text
  count
---------
 1000000
(1 row)
```
На реплике аварийно завершается основной процесс:
```sh
student$ sudo kill -QUIT $(sudo head -n 1 /var/lib/pgpro/ent-16-prod/postmaster.pid)
```
Пока реплика простаивает, на основном сервере изменим тысячу строк:
```sql
=> UPDATE t1 SET msg = msg || '!' WHERE msg ~ '000$';
```
```sql
UPDATE 1000
```
Если реплика долго простаивала, ее синхронизации может занять долгое время, даже если все нужные журнальные файлы еще сохранились на основном сервере. Мы хотим ускорить синхронизацию, передав данные с мастера на реплику командой catchup, которая будет передавать только измененные страницы.
Используем режим инкрементального копирования DELTA, укажем пути к каталогам данных. Дополнительный файл конфигурации не копируем:
```sh
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
```
```text
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)» — она показывает отношение объема переданных для синхронизации страниц к их общему объему. Чем меньше значение, тем эффективнее работает синхронизация.
Запустим реплику.
```sh
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 {#source-page-032}

```text
waiting for server to start..................... done
server started
```
```sh
student$ psql -p 5434 pgpro_probackup_2
```
Проверим данные на реплике:
```sql
=> SELECT count(*) FROM t1 WHERE msg ~ '!$';
```
```text
 count
-------
  1000
(1 row)
```
Все измененные строки синхронизированы.

## Page 33: Итоги {#source-page-033}

**Утилита pg\\\_probackup поддерживает инкрементальное копирование и инкрементальное восстановление измененных страниц**
- При наличии архива WAL поддерживается восстановление на момент в прошлом
- Возможно восстановление части данных кластера и эффективная синхронизация двух кластеров

## Page 34: Практика {#source-page-034}

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

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

4. Аварийно завершите основной процесс экземпляра. Измените файл основного слоя таблицы средствами ОС, например:

```text
dd if=/dev/urandom of=файл conv=fdatasync bs=8K count=10
```

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

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

Создадим и подготовим каталог копий.
```sh
student$ sudo mkdir /var/probackup
```
```sh
student$ sudo chown student: /var/probackup
```
Инициализируем каталог.
```sh
student$ pg_probackup init -B /var/probackup
```
```text
INFO: Backup catalog '/var/probackup' successfully initialized
```
Регистрируем экземпляр.
```sh
student$ pg_probackup add-instance \
  -B /var/probackup --instance ent-16 \
  -D /var/lib/pgpro/ent-16 \
  --remote-host=localhost \
  --remote-user=postgres
```
```text
INFO: Instance 'ent-16' successfully initialized
```
Создадим базу данных.
```sql
=> CREATE DATABASE pgpro_probackup_2 OWNER backup TEMPLATE templateprobackup;
```
```sql
CREATE DATABASE
```
```sh
student$ psql
```
```sql
=> \c pgpro_probackup_2
```
```text
You are now connected to database "pgpro_probackup_2" as user "student".
```
Запомним в настройках конфигурации атрибуты подключения.
```sh
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.
```sql
=> ALTER SYSTEM SET archive_mode = on;
```
```sql
ALTER SYSTEM
```
```sql
=> 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';
```
```sql
ALTER SYSTEM
```
Перезапустим сервер:
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
Проверим работу архивирования WAL.
```sql
=> SELECT pg_switch_wal();
```
```text
 pg_switch_wal
---------------
 0/BF4DC8C
(1 row)
```
```sql
=> CREATE TABLE t AS SELECT 'Тест архивирования WAL.' msg;
```
```sql
SELECT 1
```

## Page 36: Page 36 {#source-page-036}

Проверим, попал ли сегмент WAL в архив.
```sh
student$ pg_probackup show \
  -B /var/probackup \
  --archive
```
```text
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, помещенных в архив:
```sh
student$ ls -R /var/probackup/wal/ent-16
```
```text
/var/probackup/wal/ent-16:
00000001000000000000000B.zst
```
По умолчанию сжатие производится методом zstd.
Теперь сделаем полную резервную копию со сжатием.
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  --compress \
  -b FULL
```
### 2. Инкрементальная копия
Добавим строку в таблицу.
```sql
=> INSERT INTO t VALUES('Еще одна строка.');
```
```sql
INSERT 0 1
```
Сформируем инкрементальную копию, тоже со сжатием.
```sh
student$ pg_probackup backup \
  -B /var/probackup --instance ent-16 \
  --compress \
  -b PAGE
```
Содержимое каталога копий:
```sh
student$ pg_probackup show \
  -B /var/probackup --instance ent-16
```
```text
==========================================================================================
======================================================
 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. Восстановление из сжатой резервной копии
Остановим экземпляр.
```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
Удалим содержимое PGDATA.
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16/*
```
Восстановим экземпляр из цепочки резервных копий.
```sh
student$ pg_probackup restore \
  -B /var/probackup --instance ent-16 \
  -i TIUR8G \
  --archive-host=localhost \
  --archive-user=student
```

## Page 37: Page 37 {#source-page-037}

Запустим экземпляр.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
```sql
=> SELECT * FROM t;
```
```text
           msg
-------------------------
 Тест архивирования WAL.
 Еще одна строка.
(2 rows)
```
Данные восстановлены.
### 4. Авария сервера
Определим физический путь к файлу, содержащему страницы таблицы t.
```sql
=> SELECT pg_relation_filepath('t');
```
```text
 pg_relation_filepath
----------------------
 base/16541/16542
(1 row)
```
На сервере происходит авария.
```sh
student$ sudo kill -QUIT $(sudo head -n 1 /var/lib/pgpro/ent-16/postmaster.pid)
```
Сымитируем физическую порчу файла данных, записав в него 10 страниц (80 килобайт) случайных данных:
```sh
postgres$ dd if=/dev/urandom of=/var/lib/pgpro/ent-16/base/16541/16542 conv=fdatasync bs=8K count=10
```
```text
10+0 records in
10+0 records out
81920 bytes (82 kB, 80 KiB) copied, 0,132144 s, 620 kB/s
```
Запустим сервер.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
Попытаемся обратиться к таблице.
```sql
=> SELECT * FROM t;
```
```text
WARNING:  page verification failed, calculated checksum 6184 but expected 30746
ERROR:  invalid page in block 1 of relation base/16541/16542
```
### 5. Инкрементальное восстановление таблицы
Мы хотим восстановить испорченные страницы, не копируя при этом остальные данные кластера.
Остановим сервер.
```sh
student$ sudo systemctl stop postgrespro-ent-16.service
```
Выполним инкрементальное восстановление в режиме CHECKSUM.
```sh
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
```
```text
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 {#source-page-038}

```sql
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 мегабайт.
Запустим сервер.
```sh
student$ sudo systemctl start postgrespro-ent-16.service
```
```sh
student$ psql pgpro_probackup_2
```
Таблица восстановлена:
```sql
=> SELECT * FROM t;
```
```text
           msg
-------------------------
 Тест архивирования WAL.
 Еще одна строка.
(2 rows)
```
### Уборка
Удалим созданную базу данных и каталог копий, сбросим настройки параметров конфигурации.
```sql
=> \c student
```
```text
You are now connected to database "student" as user "student".
```
```sql
=> DROP DATABASE pgpro_probackup_2 WITH (FORCE);
```
```sql
DROP DATABASE
```
```sh
student$ sudo rm -rf /var/probackup
```
```sql
=> ALTER SYSTEM RESET ALL;
```
```sql
ALTER SYSTEM
```
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
