Привет, Хабр!
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 проведут несколько бесплатных уроков, на которые все желающие могут зарегистрироваться по ссылкам ниже:
Комментарии (3)
Sleuthhound
15.01.2024 07:47+1Вот такому жесткачу и учат на курсах, а потом приходят эти чудо-дба и ничего не могут сделать
Melkij
wal_level = archive давным-давно deprecated псевдоним для wal_level = replica
неверно. Слот физической репликации - это механизм, гарантирующий что у вас переполнится диск на мастере, но не будут удалены WAL, о получении которых ещё не отчиталась реплика.
Соответственно, вы вообще никак не пояснили, зачем вам вообще слот репликации. (хинт: он просто не нужен для pitr)
Где вы нашли синтаксис ALTER SLOT для меня, конечно, загадка. Нет такой синтаксической конструкции даже в pg17.
Ну и последнее, но самое важное: вся статья исключительно по EOL версиям postgresql и не подходит для более новых. pg_xlog* функций не существует с pg10, а чтение файла с именем recovery.conf удалил лично я начиная с postgresql 12. Это конечно объясняет пример с archive wal_level, зато вызывает вопросы к "онлайн-курсу"
Roman2dot0
Судя по ALTER SLOT статью писал chatGPT.