Непрерывное архивирование и восстановление на момент времени (Point-in-Time Recovery, PITR)

Обзор

PostgreSQL записывает каждое изменение, внесенное в файлы базы данных, в журнал предзаписи WAL (write-ahead log). Файлы WAL находятся в каталоге pg_wal. По умолчанию ADPG размещает этот каталог по следующему пути: /pg_data1/adpg14/pg_wal, где /pg_data1 — значение параметра Data directory. За дополнительной информацией об этом параметре можно обратиться к статье Конфигурационные параметры. В случае сбоя системы PostgreSQL воспроизводит действия из записей WAL, сделанных с момента последней контрольной точки.

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

  • В качестве начальной точки для восстановления необязательно иметь полностью согласованную копию на уровне файлов. Когда PostgreSQL применяет записи WAL, он исправляет любые несоответствия в резервной копии. Для него не нужна возможность делать снепшоты файловой системы, и можно использовать tar или аналогичный инструмент архивации.

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

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

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

ПРИМЕЧАНИЕ
Утилиты pg_dump и pg_dumpall не создают резервные копии на уровне файловой системы и не могут использоваться как часть решения для непрерывного архивирования.

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

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

Настройка архивирования WAL

PostgreSQL создает бесконечно длинную последовательность записей WAL. Система делит эту последовательность на файлы-сегменты WAL, размер которых обычно составляет 16 МБ. Файлы сегментов имеют числовые имена, отражающие их положение в абстрактной последовательности WAL. Если сервер не использует архивирование WAL, система создает несколько файлов сегментов, а затем "перерабатывает" (recycle) их, переименовывая ненужные файлы сегментов в сегменты с большими порядковыми номерами. Предполагается, что файлы сегментов, содержимое которых предшествует последней контрольной точке, могут быть переработаны.

Чтобы заархивировать данные WAL, необходимо где-нибудь сохранить содержимое каждого файла сегмента после его заполнения до того, как файл сегмента будет переработан. Например, можно скопировать файлы сегментов в каталог, подключенный к NFS, на другом компьютере или записать их на внешний диск. PostgreSQL позволяет администратору указать команду оболочки для создания копии завершенного файла сегмента. Команда может быть простой или вызывать shell-скрипт.

Чтобы включить архивирование WAL, установите значение replica или выше для конфигурационного параметра wal_level, для параметра archive_mode — значение on и укажите команду оболочки для archive_command. Используйте секцию postgresql.conf custom section на вкладке Clusters → ADPG cluster → Services → ADPG → Primary configuration в пользовательском интерфейсе ADCM, чтобы указать эти параметры. Описание postgresql.conf custom section можно найти в статье Конфигурационные параметры.

В archive_command используйте %p вместо пути к архивируемому файлу и %f вместо имени файла. Путь к архивируемому файлу задаётся относительно каталога данных кластера. Например, следующая команда archive_command копирует сегменты WAL в каталог /mnt/server/archived:

archive_command : 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'

Во время выполнения сервер заменяет параметры %p и %f значениями, и команда может выглядеть следующим образом:

test ! -f /mnt/server/archivedir/0000000600000000000000A0 && cp pg_wal/0000000600000000000000A0 /mnt/server/archivedir/0000000600000000000000A0

Аналогичная команда генерируется для каждого нового архивируемого файла. Команда архивирования выполняется от имени того же пользователя, который запускает ADPG.

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

Пример определения параметра archive_command с shell-скриптом:

archive_command : 'local_backup_script.sh "%p" "%f"'

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

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

Когда команда архивирования завершается сигналом (отличным от SIGTERM, получаемым при штатном отключении сервера) или при возникновении ошибки оболочки (например, если команда не найдена), процесс архивирования прерывается и перезапускается управляющим процессом postmaster. В таких случаях в pg_stat_archiver не сообщается об ошибке.

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

Вы также можете заставить сервер переключиться на новый файл WAL с помощью функции pg_switch_wal, если хотите заархивировать завершенную транзакцию как можно скорее. Другие функции, связанные с управлением WAL, перечислены в разделе Backup Control Functions.

Создание базовой резервной копии

Вы можете использовать утилиту pg_basebackup, как описано в статье Резервное копирование на уровне файловой системы, чтобы создать базовую резервную копию.

Чтобы использовать резервную копию, вам необходимо сохранить все файлы сегментов WAL, созданные во время и после резервного копирования файловой системы. Процесс базового резервного копирования создает файл истории резервного копирования, который хранится в каталоге архива WAL. Этот файл назван так же, как первый файл сегмента WAL, необходимый для резервного копирования файловой системы. Например, если начальный файл WAL имеет имя 0000000100001234000055CD, файл истории резервного копирования будет называться 0000000100001234000055CD.007C9330.backup. Вторая часть имени файла указывает точную позицию в файле WAL и может быть проигнорирована.

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

Использование низкоуровневого API для создания базовой резервной копии

Базовые резервные копии низкого уровня могут быть сделаны немонопольным или монопольным способом. Рекомендуется использовать немонопольным метод, так как монопольный метод считается устаревшим. Немонопольным резервное копирование позволяет запускать другие параллельные процессы резервного копирования, которые могут использовать то же API резервного копирования или утилиту pg_basebackup.

Создание базовой резервной копии с помощью низкоуровневого API содержит больше шагов, чем метод с использованием pg_basebackup. Очень важно, чтобы эти шаги выполнялись по порядку, и следующий шаг выполнялся только в случае успеха предыдущего.

  1. Убедитесь, что архивирование WAL включено и работает.

  2. Подключитесь к серверу как пользователь, у которого есть права на запуск функции pg_start_backup, и выполните команду:

    SELECT pg_start_backup('label', false, false);

    Функция pg_start_backup имеет следующий синтаксис:

    pg_start_backup(<уникальный_идентификатор>, <быстрая_архивная_копия>, <монопольное_копирование>)

    Где:

    • уникальный_идентификатор — строка, являющаяся уникальным идентификатором операции резервного копирования.

    • быстрая_архивная_копия — по умолчанию, pg_start_backup может работать длительное время, так как pg_start_backup выполняет контрольную точку, а операции ввода-вывода, необходимые для контрольной точки, распределяются на значительный период времени, равный половине интервала между контрольными точками. Обратитесь к статье checkpoint_completion_target за дополнительной информацией. Это сводит к минимуму влияние на обработку запросов. Если вы хотите начать резервное копирование как можно скорее, измените второй параметр на true. В этом случае контрольная точка будет выполнена немедленно без ограничения объёма операций ввода/вывода.

    • монопольное_копирование — определяет, будет ли pg_start_backup инициировать монопольное базовое резервное копирование. В нашем примере производится немонопольное копирование.

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

  3. Создайте резервную копию, применяя любой способ резервного копирования файловой системы. Обратитесь к статье Backing up the data directory за дополнительной информацией о том, какие каталоги должны быть скопированы.

  4. Используя то же соединение, что на шаге 2, вызовите функцию pg_stop_backup:

    SELECT * FROM pg_stop_backup(false, true);

    Функция pg_stop_backup имеет следующий синтаксис:

    pg_stop_backup(<монопольное_копирование>, <ожидание_архивирования_wal>)

    Где:

    • монопольное_копирование — указывает, используется ли монопольный режим при создании резервной копии. Этот параметр должен соответствовать значению из вызова pg_start_backup.

    • ожидание_архивирования_wal — определяет, должна ли pg_stop_backup ждать, пока файлы WAL будут заархивированы.

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

      Функция pg_stop_backup возвратит одну строку с тремя значениями. Второе из них нужно записать в файл backup_label в корневом каталоге резервной копии. Третье значение, если оно не пустое, должно быть записано в файл tablespace_map. Эти файлы являются критическими для восстановления копии и должны быть записаны байт за байтом без изменений, для чего может потребоваться открыть файл в двоичном редакторе.

  5. Необходимо заархивировать файлы сегментов WAL, активные во время создания резервной копии. Функция pg_stop_backup в первом возвращаемом значении указывает, какой последний сегмент WAL требуется для формирования полного набора файлов резервной копии. На ведущем сервере, если включён режим архивации (параметр archive_mode равен on) и аргумент wait_for_archive функции pg_stop_backup равен true, функция pg_stop_backup не завершится, пока не будет заархивирован последний сегмент. На резервном сервере значением archive_mode должно быть always, чтобы pg_stop_backup ожидала архивации. Так как параметр archive_command задан, эти файлы будут заархивированы автоматически.

Восстановление непрерывной архивной копии

Для восстановления из резервной копии выполните следующие действия:

  1. Остановите сервер.

  2. Скопируйте каталог данных кластера и все табличные пространства во временное хранилище. Эта операция требует, чтобы в вашей системе было достаточно свободного места для хранения двух копий базы данных. Если у вас недостаточно места для сохранения всех данных, необходимо сохранить содержимое каталога pg_wal, потому что в нем могут быть файлы, которые не были заархивированы до системного сбоя.

  3. Удалите все существующие файлы и подкаталоги в каталоге данных кластера и корневых каталогах всех табличных пространств.

  4. Восстановите файлы базы данных из резервной копии файловой системы. Убедитесь, что они восстановлены с правильным владельцем (пользователь, запускающий сервер, а не root) и с правильными разрешениями. Если вы используете табличные пространства, проверьте правильность восстановления символьных ссылок в pg_tblspc/.

  5. Удалите все файлы, присутствующие в pg_wal/. Эти файлы взяты из резервной копии файловой системы и поэтому, скорее всего, они будут более старыми, чем текущие. Если вы не использовали pg_wal/, создайте этот каталог заново с соответствующими правами, а если вы использовали символьную ссылку, восстановите ее.

  6. Если у вас есть незархивированные файлы сегментов WAL, которые вы сохранили на шаге 2, скопируйте их в pg_wal/. Не перемещайте их, чтобы у вас остались неизмененные файлы, если возникнет проблема, и всё придётся начинать сначала.

  7. Установите параметры восстановления в postgresql.conf custom section и создайте файл recovery.signal в каталоге данных кластера (каталог данных в ADPG по умолчанию — /pg_data1/adpg14). Вы также можете временно изменить секцию PG_HBA в пользовательском интерфейсе ADCM, чтобы запретить подключение пользователей до тех пор, пока система не будет восстановлена.

  8. Запустите сервер. Сервер перейдёт в режим восстановления и считает необходимые архивные файлы WAL. Если восстановление прервалось из-за внешней ошибки, сервер можно перезапустить, и восстановление продолжится. По завершении процесса восстановления сервер удалит recovery.signal, чтобы предотвратить случайный повторный вход в режим восстановления, и начнёт стандартные операции с базой данных.

  9. Проверьте содержимое базы данных и убедитесь, что желаемое состояние восстановлено. Если это так, отредактируйте раздел PG_HBA, чтобы разрешить пользователям подключаться к восстановленной базе данных. В противном случае вернитесь к шагу 1.

На шаге 7 необходимо задать конфигурацию восстановления, описывающую, как будет выполняться восстановление и до какой точки. Используйте параметр restore_command, указывающий как извлекать файлы WAL из архива. Этот параметр подобен archive_command. Он должен содержать команду оболочки с %p вместо пути, куда будут копироваться файлы WAL и %f вместо имени файла журнала. Путь задаётся относительно каталога данных кластера.

Пример:

restore_command : 'cp /mnt/server/archivedir/%f %p'

Параметр restore_command также может содержать shell-скрипт.

Если сервер не может найти сегменты WAL в архиве, он ищет их в каталоге pg_wal/. Это позволяет использовать последние незаархивированные сегменты. Сегменты из архива имеют более высокий приоритет, чем файлы из pg_wal/.

Процесс восстановления обрабатывает все доступные сегменты WAL и восстанавливает базу данных на текущий момент времени или как можно ближе к этому моменту с учетом доступных сегментов WAL. Поэтому восстановление заканчивается сообщением "файл не найден", точный текст сообщения об ошибке зависит от текущей команды restore_command. Вы также можете увидеть сообщение об ошибке в начале восстановления для файла с именем, похожим на 00000001.history. Это также не указывает на проблему в большинстве случаев. За дополнительной информацией обратитесь к разделу Timelines.

Если нужно восстановиться до какого-то предыдущего момента времени, укажите точку остановки. Вы можете задать точку остановки (recovery target) по дате/времени, именованной точке восстановления или по завершению транзакции с определенным идентификатором. На данный момент полезным может быть только указание даты/времени или имени точки восстановления, пока нет никаких средств, позволяющих точно определить, какой идентификатор транзакции нужно выбрать.

Если процесс восстановления обнаруживает поврежденные данные WAL, восстановление останавливается на этом этапе и сервер не запускается. В этом случае запустите процесс восстановления с самого начала и укажите точку остановки (recovery target) перед точкой повреждения. Восстановление сможет завершиться удачно. Если восстановление завершается сбоем по внешней причине, такой как системный сбой или недоступность архива WAL, восстановление можно запустить заново, и оно начнется с точки сбоя. Перезапуск восстановления работает так же, как контрольные точки, сервер периодически сохраняет текущее состояние на диск и обновляет файл pg_control. Таким образом, уже обработанные файлы WAL не сканируются повторно.

Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней