Pull to refresh
952.85
OTUS
Цифровые навыки от ведущих экспертов

PITR в PostgreSQL

Reading time6 min
Views4.3K

Привет, Хабр!

Cколько раз вы сталкивались с ситуацией, когда что-то пошло не так и вам необходимо было в срочном порядке восстановить данные из бдшки, причем так, чтобы это было максимально близко к определенному моменту в прошлом? PITR – наш герой, спасающий наши нервы.

Компоненты PITR в постгресе

WAL

Когда вносятся изменения в бдшку, они не сразу же применяются к самой базе данных. Вместо этого они записываются в специальные журналы, называемые Write-Ahead Logs. Это происходит до момента, когда система подтверждает, что изменения были успешно записаны в журнал. WAL-журнал можно представить как своего рода журнал логов, который детально фиксирует все операции с данными, производимые в базе данных.

К примеру отрывок журнала может выглядеть так:

RMgr: HEAP2         XLogRecPtr: 0/16B6D8
xl_info: INSERT_LEAF        dbid: 12345   relid: 67890
xl_len: 45                  bucket_id: 2  blkref #0: rel 1663/12345/67890 blk 1
--------
rmgr: Transaction    len (rec/tot):    34/    34, tx:       131, lsn: 0/16B7848, prev 0/16B7820, desc: COMMIT 2024-01-13 10:15:12.345678+00, rels: C 1663/12345/67890
--------
RMgr: INDEX          XLogRecPtr: 0/16B7908
xl_info: INSERT       dbid: 12345   relid: 54321
xl_len: 60            blkref #0: rel 1663/12345/54321 blk 1

Первые три строчки относятся к вставке в листья древовидной структуры (как часть B-tree индекса). Это указывает на операцию вставки в определенную таблицу с идентификатором relid 67890 в базе данных с dbid 12345.

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

Последние строчки относятся к операции вставки в индекс (relid 54321) для базы данных с идентификатором 12345.

Эти записи содержат различные технические детали, такие как идентификаторы транзакций (tx), указатели на местоположение записей в журнале (XLogRecPtr), размеры записей (xl_len), идентификаторы баз данных (dbid) и таблиц (relid), а также информацию о блоках данных, на которые влияют эти операции (blkref).

Бэкапы и базовый снимок

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

Непрерывное архивирование изменений

Непрерывное архивирование работает в тандеме с WAL и представляет собой постоянное сохранение вал журналов. Эти журналы фиксируют все изменения, происходящие в базе данных. Каждый раз, когда происходит изменение в базе данных, оно фиксируется в журнале и немедленно отправляется в архив. Это создает последовательность архивов, представляющих собой историю изменений в базе данных.

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

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

Настройка и конфигурация PITR в PostgreSQL

Для начала необходимо включить режим архивирования в конфигурационном файле постгреса. Допустим, вы используете файл postgresql.conf:

wal_level = archive
archive_mode = on
archive_command = 'команда_архивации %p %f'

wal_level задает уровень журналирования. archive_mode включает или отключает режим архивации. archive_cmmand определяет команду, которая будет выполняться при каждой записи в WAL. %p и %f - макросы, предоставляющие путь к журналу и его имя.

Команды архивации могут быть следующими:

Простое копирование WAL файлов в каталог архивации

archive_command = 'cp %p /path/to/archive/%f'

Эта команда скопирует текущий WAL файл в /path/to/archive/ с тем же именем.

Архивация с сжатием WAL файлов

Можно использовать утилиту gzip:

archive_command = 'gzip < %p > /path/to/archive/%f.gz'

Архивация с добавлением временной метки к файлам

archive_command = 'cp %p /path/to/archive/%f_$(date +%Y%m%d%H%M%S)'

После активации режима архивации создаем директорию для хранения архивов:

mkdir /path/to/archive

Прежде чем начать архивацию, создадим базовый снимок базы данных:

pg_basebackup -D /path/to/backup -Ft -Xs -P -U username -h host -p yourport

-D указывает путь для сохранения снимка. -Ft определяет формат снимка как tar. -Xs включает streaming replication для создания точной копии базы данных. -P выводит прогресс создания снимка. -U указывает имя пользователя PostgreSQL. -h и -p определяют хост и порт PostgreSQL.

Прежде чем использовать слот репликации в PostgreSQL, необходимо создать этот слот в базе данных. Слот репликации - это механизм, который испоьзуется для передачи WAL записей от мастера к реплике без необходимости активного участия реплики.

Для создания слота репликации нужно подключиться к мастер-серверу PostgreSQL.

Далее создать слот репликации с помощью команды pg_create_physical_replication_slot:

SELECT pg_create_physical_replication_slot('slot_name');

Где 'slot_name' - это имя, которое вы выбираете для слота. Это имя должно быть уникальным в контексте данного мастер-сервера.

Можно настроить различные параметры слота, такие как максимальный размер хранимых WAL файлов и другие параметры, к примеру:

SELECT pg_create_physical_replication_slot('my_replication_slot');

-- В этом примере устанавливаем максимальный размер WAL файлов в 100MB и включаем режим сжатия WAL
ALTER SLOT my_replication_slot SET (max_replication_size = '100MB', wal_compression = on);

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

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

Простой сценарий shell для регулярного резервного копирования WAL-журналов:

#!/bin/bash
while true; do
    for file in $(find /path/to/pg_xlog -type f); do
        cp "$file" /path/to/archive
    done
    sleep 300  # Периодичность резервного копирования в секундах
done

Команда для восстановления базы данных до определенного момента времени:

pg_ctl stop -D /path/to/data
rm -rf /path/to/data/*
pg_basebackup -D /path/to/data -Ft -Xs -P -U your_username -h your_host -p your_port
# Восстановление до конкретного момента времени (replace XID and timestamp with actual values)
pg_ctl start -D /path/to/data
pg_waldump /path/to/archive/000000010000000000000001 | grep "xid: [XID]" | grep "[timestamp]"

Можно использовать rsync для автоматической архивации WAL-журналов на удаленный сервер:

#!/bin/bash
while true; do
    rsync -av --delete /path/to/pg_xlog remote_user@remote_host:/path/to/remote_archive
    sleep 300  # Периодичность архивации в секундах
done

Восстановление данных

Первый шаг - определить точку времени, к которой вы хотите восстановить данные. Это может быть конкретная дата и время или LSN:

SELECT pg_xlogfile_name(pg_current_xlog_location());

Перед восстановлением необходимо остановить PostgreSQL:

sudo service postgresql stop

Очищаем или переименовываем каталог данных PostgreSQL (предположим, что он находится в /var/lib/postgresql/12/main):

mv /var/lib/postgresql/12/main /var/lib/postgresql/12/main_backup

Восстанавливаем базовую резервную копию (которая была создана во время настройки PITR) в каталог данных:

pg_restore -D /var/lib/postgresql/12/main /path/to/base/backup

Создаем файл recovery.conf в каталоге данных с указанием метода восстановления и целевого времени или LSN:

restore_command = 'cp /path/to/archivedir/%f %p'
recovery_target_time = '2024-01-10 14:00:00'
# или recovery_target_lsn = '0/3000DB0'

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

Теперь можно запустить PostgreSQL:

sudo service postgresql start

PostgreSQL автоматически начнет процесс восстановления, применяя журналы транзакций до указанной точки времени или LSN.

После завершения восстановления постгрес переименует recovery.conf в recovery.done.


PITR как механизм восстановления, позволяет адаптироваться к неожиданным ситуациям и минимизировать потерю данных при возникновении сбоев.

Больше практических навыков вы можете получить в рамках онлайн-курса PostgreSQL для администраторов баз данных и разработчиков. В преддверии запуска курса, мои коллеги из OTUS проведут несколько бесплатных уроков, на которые все желающие могут зарегистрироваться по ссылкам ниже:

Tags:
Hubs:
Total votes 20: ↑13 and ↓7+6
Comments3

Articles

Information

Website
otus.ru
Registered
Founded
Employees
101–200 employees
Location
Россия
Representative
OTUS