25.3. Continue Archiving and Point-in-Time Recovery (PITR)#

25.3. Continue Archiving and Point-in-Time Recovery (PITR)

25.3. Continue Archiving and Point-in-Time Recovery (PITR)

В любое время Tantor SE поддерживает журнал с предварительной записью (WAL) в подкаталоге pg_wal/ каталога данных кластера. Журнал записывает каждое изменение, внесенное в файлы данных базы данных. Этот журнал существует в основном для обеспечения безопасности при сбое: если система выйдет из строя, база данных может быть восстановлена до согласованного состояния путем повторного воспроизведения записей журнала, сделанных с момента последней контрольной точки. Однако наличие журнала позволяет использовать третью стратегию резервного копирования баз данных: можно объединить резервное копирование на уровне файловой системы с резервным копированием файлов журнала предзаписи. Если требуется восстановление, мы восстанавливаем резервную копию файловой системы, а затем повторно воспроизводим записи из резервных копий файлов журнала предзаписи, чтобы привести систему в актуальное состояние. Этот подход сложнее в управлении, чем любой из предыдущих подходов, но он имеет некоторые значительные преимущества:

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

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

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

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

Примечание

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

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

Чтобы успешно восстановиться с использованием непрерывной архивации (также называемой "онлайн-резервным копированием" многими поставщиками баз данных), вам необходима непрерывная последовательность архивных файлов журнала предзаписи, которая простирается назад, по крайней мере, до времени начала вашего резервного копирования. Поэтому, чтобы начать, вам следует настроить и протестировать процедуру архивации файлов журнала предзаписи перед тем, как сделать первое базовое резервное копирование. Следовательно, мы сначала обсудим механику архивации файлов журнала предзаписи.

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

В абстрактном смысле, работающая система Tantor SE производит бесконечную последовательность записей WAL. Система физически разделяет эту последовательность на файлы WAL сегментов, которые обычно имеют размер 16 МБ (хотя размер сегмента может быть изменен во время initdb). Сегменты файлов получают числовые имена, отражающие их позицию в абстрактной последовательности WAL. Когда не используется архивирование WAL, система обычно создает только несколько сегментных файлов, а затем переиспользует их, переименовывая файлы сегментов, которые больше не нужны, в более высокие номера сегментов. Предполагается, что сегментные файлы, содержимое которых предшествует последней контрольной точке, больше не представляют интереса и могут быть переиспользованы.

При архивировании данных WAL нам необходимо захватывать содержимое каждого сегментного файла после его заполнения и сохранять эти данные где-то, прежде чем сегментный файл будет повторно использован. В зависимости от приложения и доступного оборудования может быть множество различных способов "сохранения данных где-то": можно скопировать сегментные файлы в каталог, смонтированный по NFS на другой машине, записать их на магнитную ленту (обеспечивая способ идентификации исходного имени каждого файла), объединить их вместе и записать на CD или что-то еще полностью отличное. Чтобы предоставить администратору базы данных гибкость, Tantor SEне делает никаких предположений о том, как будет выполняться архивирование. Вместо этого Tantor SEпозволяет администратору указать команду оболочки или библиотеку архива, которая будет выполнена для копирования завершенного сегментного файла в нужное место. Это может быть такой простой командой оболочки, как cp, или она может вызывать сложную функцию на языке C - все зависит от вас.

Для включения архивирования WAL установите параметр конфигурации wal_level в значение replica или выше, параметр archive_mode в значение on, укажите команду оболочки для использования в параметре конфигурации archive_command или укажите библиотеку для использования в параметре конфигурации archive_library. На практике эти настройки всегда будут размещены в файле postgresql.conf.

В archive_command переменная, %p, заменяется на путь к файлу для архивации, а %f - только на имя файла. (Путь относительно текущего рабочего каталога, т.е. каталога данных кластера). Используйте %%, если вам нужно вставить фактический символ % в команду. Самая простая полезная команда может выглядеть так:

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'  # Unix
archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows

который скопирует архивные сегменты WAL в каталог /mnt/server/archivedir. (Это пример, а не рекомендация, и может не работать на всех платформах). После замены параметров %p и %f, фактическая выполняемая команда может выглядеть так:

test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_wal/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065

Для каждого нового файла, который нужно архивировать, будет сгенерирована аналогичная команда.

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

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

Еще один способ архивирования - использовать пользовательский модуль архивации в качестве archive_library. Поскольку такие модули написаны на C, создание собственного модуля может потребовать значительно больше усилий, чем написание команды оболочки. Однако модули архивации могут быть более производительными, чем архивирование через оболочку, и они будут иметь доступ к многим полезным ресурсам сервера. Дополнительную информацию о модулях архивации см. в разделе Глава 49.

Когда команда архивации завершается сигналом (кроме SIGTERM, который используется при завершении работы сервера) или ошибкой оболочки с кодом возврата больше 125 (например, команда не найдена), или если функция архивации выдает ERROR или FATAL, процесс архиватора прерывается и перезапускается постмастер. В таких случаях сбой не отображается в pg_stat_archiver.

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

Рекомендуется протестировать вашу предлагаемую команду архивации или библиотеку, чтобы убедиться, что они действительно не перезаписывают существующий файл и возвращают ненулевой статус или false соответственно в этом случае. Приведенная выше команда для Unix обеспечивает это, включая отдельный шаг test. На некоторых платформах Unix команда cp имеет переключатели, такие как -i , которые можно использовать для выполнения того же действия менее подробно, но не следует полагаться на них, не проверив, что возвращается правильный код завершения. (В частности, GNU cp вернет нулевой статус, когда используется -i и целевой файл уже существует, что не является желаемым поведением).

При проектировании системы архивирования учтите, что произойдет, если команда архивации или библиотека несколько раз не смогут выполниться из-за требования вмешательства оператора или из-за нехватки места в архиве. Например, это может произойти, если вы записываете на ленту без автоматического сменного устройства; когда лента заполняется, невозможно производить дальнейшую архивацию до тех пор, пока лента не будет заменена. Вы должны обеспечить адекватное сообщение об ошибке или запросе оператору, чтобы ситуация могла быть разрешена достаточно быстро. Каталог pg_wal/ будет продолжать заполняться файлами сегментов WAL до тех пор, пока ситуация не будет разрешена. (Если файловая система, содержащая каталог pg_wal/, заполнится, Tantor SE выполнит аварийное выключение. Никакие подтвержденные транзакции не будут потеряны, но база данных останется офлайн до освобождения некоторого пространства).

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

При написании команды архивации или библиотеки следует предполагать, что имена файлов для архивации могут быть длиной до 64 символов и могут содержать любую комбинацию букв ASCII, цифр и точек. Необходимо сохранить оригинальное относительное расположение файла (%p) не требуется, но необходимо сохранить имя файла (%f).

Обратите внимание, что хотя архивирование WAL позволит восстановить все изменения, внесенные в данные в вашей базе данных Tantor SE, оно не восстановит изменения, внесенные в файлы конфигурации (то есть postgresql.conf, pg_hba.conf и pg_ident.conf), поскольку они редактируются вручную, а не через SQL-операции. Возможно, вам захочется сохранить файлы конфигурации в месте, которое будет резервироваться вашими обычными процедурами резервного копирования файловой системы. См. Раздел 19.2 для получения информации о том, как переместить файлы конфигурации.

Команда архивации или функция вызываются только для завершенных сегментов WAL. Следовательно, если ваш сервер генерирует только небольшой трафик WAL (или имеет периоды простоя, когда это происходит), между завершением транзакции и ее безопасной записью в архивное хранилище может быть длительная задержка. Чтобы ограничить возраст неархивированных данных, вы можете установить archive_timeout, чтобы заставить сервер переключаться на новый файл сегмента WAL хотя бы столько раз. Обратите внимание, что архивированные файлы, которые архивируются раньше из-за принудительного переключения, все равно имеют ту же длину, что и полностью заполненные файлы. Поэтому не рекомендуется устанавливать очень короткий archive_timeout - это приведет к раздутию вашего архивного хранилища. Обычно разумными являются значения archive_timeout в минуту или около того.

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

Когда wal_level установлен в minimal, некоторые SQL-команды оптимизируются для избежания записи в WAL, как описано в Раздел 14.4.7. Если архивирование или потоковая репликация были включены во время выполнения одного из этих операторов, в WAL не будет достаточно информации для восстановления из архива. (Восстановление после сбоя не затрагивается). Поэтому wal_level может быть изменен только при запуске сервера. Однако archive_command и archive_library могут быть изменены с помощью перезагрузки файла конфигурации. Если вы архивируете через оболочку и хотите временно остановить архивирование, один из способов сделать это - установить archive_command в пустую строку (''). Это приведет к накоплению WAL-файлов в каталоге pg_wal/ до тех пор, пока не будет установлена рабочая archive_command.

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

Самый простой способ выполнить базовое резервное копирование - использовать инструмент pg_basebackup. Он может создавать базовое резервное копирование как обычные файлы, так и в виде tar-архива. Если требуется больше гибкости, чем может предоставить pg_basebackup, можно также создать базовое резервное копирование с использованием низкоуровневого API (см. Раздел 25.3.3).

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

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

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

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

25.3.3. Создание базовой резервной копии с использованием низкоуровневого API

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

Возможно одновременное выполнение нескольких резервных копий (как тех, которые запущены с использованием этого API резервного копирования, так и тех, которые запущены с использованием pg_basebackup).

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

  2. Подключитесь к серверу (не важно к какой базе данных) в качестве пользователя с правами на выполнение функции pg_backup_start (суперпользователь или пользователь, которому было предоставлено право EXECUTE на эту функцию) и выполните команду:

    SELECT pg_backup_start(label => 'label', fast => false);
    

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

    Все резервные копии в режиме онлайн всегда запускаются в начале контрольной точки. По умолчанию, pg_backup_start будет ожидать завершения следующей регулярно запланированной контрольной точки, что может занять длительное время (см. параметры конфигурации checkpoint_timeout и checkpoint_completion_target). Это обычно предпочтительно, так как это минимизирует влияние на работающую систему. Если нужно начать резервное копирование как можно скорее, передайте true в качестве второго параметра в pg_backup_start и он запросит немедленную контрольную точку, которая завершится как можно быстрее, используя максимально возможное количество I/O.

  3. Выполните резервное копирование, используя любое удобное средство резервного копирования файловой системы, такое как tar или cpio (не pg_dump или pg_dumpall). Необходимо и не желательно останавливать нормальную работу базы данных во время выполнения этой операции. См. Раздел 25.3.3.1 для учета некоторых моментов при выполнении этого резервного копирования.

  4. В том же соединении, что и ранее, выполните команду:

    SELECT * FROM pg_backup_stop(wait_for_archive => true);
    

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

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

  5. После архивации активных файлов сегментов WAL во время резервного копирования вы закончили. Файл, идентифицированный первым возвращаемым значением функции pg_backup_stop, является последним сегментом, который требуется для формирования полного набора файлов резервной копии. На основном сервере, если archive_mode включен и параметр wait_for_archive установлен в true, функция pg_backup_stop не возвращает управление до тех пор, пока последний сегмент не будет заархивирован. На резервном сервере archive_mode должен быть всегда, чтобы функция pg_backup_stop ожидала. Архивация этих файлов происходит автоматически, так как вы уже настроили archive_command или archive_library. В большинстве случаев это происходит быстро, но рекомендуется следить за системой архивации, чтобы убедиться, что нет задержек. Если процесс архивации отстает из-за сбоев в команде архивации или библиотеке, он будет продолжать повторять попытки до тех пор, пока архивация не будет успешной и резервное копирование не будет завершено. Если нужно установить ограничение времени выполнения функции pg_backup_stop, установите соответствующее значение pg_backup_stop, но имейте в виду, что если pg_backup_stop завершается из-за этого, ваше резервное копирование может быть недействительным.

    Если процесс резервного копирования отслеживает и гарантирует, что все файлы сегментов WAL, необходимые для резервной копии, успешно архивированы, то параметр wait_for_archive (который по умолчанию установлен в true) может быть установлен в false, чтобы функция pg_backup_stop вернула управление сразу после записи записи о завершении резервного копирования в WAL. По умолчанию функция pg_backup_stop будет ожидать, пока все WAL-файлы не будут архивированы, что может занять некоторое время. Этот параметр должен использоваться с осторожностью: если архивация WAL не отслеживается правильно, то резервная копия может не содержать все файлы WAL и, следовательно, будет неполной и не сможет быть восстановлена.

25.3.3.1. Резервное копирование каталога данных

Некоторые инструменты резервного копирования файловой системы выдают предупреждения или ошибки, если файлы, которые они пытаются скопировать, изменяются во время копирования. При создании базовой резервной копии активной базы данных такая ситуация является нормальной и не является ошибкой. Однако необходимо убедиться, что вы можете отличить такие жалобы от реальных ошибок. Например, некоторые версии приложения rsync возвращают отдельный код завершения для исчезнувших исходных файлов, и вы можете написать скрипт-драйвер, чтобы принять этот код завершения как случай без ошибок. Кроме того, некоторые версии GNU tar возвращают код ошибки, неотличимый откритической ошибки, если файл был обрезан во время копирования tar. К счастью, версии GNU tar 1.16 и более поздние завершаются с кодом 1, если файл был изменен во время резервного копирования, и с кодом 2 для других ошибок. С версии GNU tar 1.23 и более поздних вы можете использовать опции предупреждения --warning=no-file-changed --warning=no-file-removed, чтобы скрыть связанные предупреждающие сообщения.

Убедитесь, что ваша резервная копия включает все файлы в каталоге кластера базы данных (например, /usr/local/pgsql/data). Если вы используете табличные пространства, которые не находятся внутри этого каталога, будьте внимательны и включите их в резервную копию (и убедитесь, что ваша резервная копия архивирует символические ссылки как ссылки, иначе восстановление повредит ваши табличные пространства).

Вы должны, однако, исключить из резервной копии файлы в подкаталоге pg_wal/ кластера. Это небольшое изменение стоит сделать, потому что оно снижает риск ошибок при восстановлении. Это легко организовать, если pg_wal/ является символической ссылкой, указывающей на место вне каталога кластера, что является стандартной настройкой для повышения производительности. Также можно исключить postmaster.pid и postmaster.opts, которые содержат информацию о работающем postmaster, а не о postmaster, который в конечном итоге будет использовать эту резервную копию. (Эти файлы могут запутать pg_ctl).

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

Содержимое каталогов pg_dynshmem/, pg_notify/, pg_serial/, pg_snapshots/, pg_stat_tmp/ и pg_subtrans/ (но не сами каталоги) можно опустить из резервной копии, так как они будут инициализированы при запуске постмастера.

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

pg_internal.init файлы могут быть не указаны из резервной копии, если найден файл с таким именем. Эти файлы содержат данные кеша отношений, которые всегда перестраиваются при восстановлении.

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

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

25.3.4. Восстановление с использованием непрерывной резервной копии архива

Хорошо, случилось самое худшее и вам нужно восстановиться из резервной копии. Вот процедура:

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

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

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

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

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

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

  7. Установите настройки восстановления в файле postgresql.conf (см. Раздел 19.5.5) и создайте файл recovery.signal в каталоге данных кластера. Возможно, вам также потребуется временно изменить файл pg_hba.conf, чтобы предотвратить подключение обычных пользователей, пока вы не убедитесь в успешном восстановлении.

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

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

Важной частью всего этого является настройка файла восстановления, который описывает, как нужно восстановить и насколько должно выполняться восстановление. Единственное, что вам абсолютно необходимо указать, это restore_command, который сообщает Tantor SE, как извлекать архивные сегменты файлов журнала предзаписи. Как и archive_command, это строка командной оболочки. Она может содержать %f, который заменяется именем желаемого файла журнала, и %p, который заменяется путем копирования файла журнала. (Путь относительно текущего рабочего каталога, т.е. каталога данных кластера). Напишите %%, если вам нужно вставить фактический символ % в команду. Самая простая полезная команда выглядит примерно так:

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

который скопирует ранее архивированные сегменты WAL из каталога /mnt/server/archivedir. Конечно, вы можете использовать что-то гораздо более сложное, возможно, даже оболочку, которая запросит оператору подключить соответствующую ленту.

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

Не все запрашиваемые файлы будут файлами сегментов WAL; также следует ожидать запросов на файлы с суффиксом .history. Также имейте в виду, что базовое имя пути %p будет отличаться от %f; не ожидайте их взаимозаменяемости.

WAL сегменты, которые не могут быть найдены в архиве, будут искаться в pg_wal/; это позволяет использовать недавно неархивированные сегменты. Однако, сегменты, доступные из архива, будут использоваться в приоритете перед файлами в pg_wal/.

Обычно восстановление будет происходить через все доступные сегменты WAL, восстанавливая базу данных до текущей точки во времени (или как можно ближе к ней, учитывая доступные сегменты WAL). Поэтому нормальное восстановление закончится сообщением "файл не найден", точный текст сообщения об ошибке зависит от вашего выбора команды восстановления restore_command. Также можно увидеть сообщение об ошибке в начале восстановления для файла с именем, например, 00000001.history. Это также нормально и не указывает на проблему в простых ситуациях восстановления; см. подробнее раздел "Резервные копии и временные линии Раздел 25.3.5".

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

Примечание

Точка остановки должна быть после времени окончания базового резервного копирования, то есть времени окончания pg_backup_stop. Вы не можете использовать базовое резервное копирование для восстановления до времени, когда это резервное копирование было в процессе. (Чтобы восстановиться до такого времени, необходимо вернуться к предыдущему базовому резервному копированию и продолжить с него).

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

25.3.5. Графики времени

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

Чтобы справиться с этой проблемой, Tantor SE имеет понятие таймлайнов. Каждый раз, когда завершается восстановление из архива, создается новый таймлайн, чтобы идентифицировать последовательность записей WAL, сгенерированных после этого восстановления. Номер идентификатора таймлайна является частью имен файлов сегментов WAL, поэтому новый таймлайн не перезаписывает данные WAL, сгенерированные предыдущими таймлайнами. Фактически, можно архивировать множество разных таймлайнов. Хотя это может показаться бесполезной функцией, она часто спасает жизни. Представьте ситуацию, когда вы не совсем уверены, к какой точке во времени восстановиться, и поэтому вам приходится делать несколько восстановлений по точкам во времени методом проб и ошибок, пока вы не найдете лучшее место для отделения от старой истории. Без таймлайнов этот процесс скоро приведет к неуправляемому беспорядку. С таймлайнами вы можете восстановиться в любое предыдущее состояние, включая состояния в ветвях таймлайнов, которые вы ранее отказались от использования.

Каждый раз, когда создается новая временная шкала, Tantor SE создает файл истории временных шкал, который показывает, от какой временной шкалы она отклонилась и когда. Эти файлы истории необходимы для того, чтобы система могла выбрать правильные файлы сегментов WAL при восстановлении из архива, содержащего несколько временных шкал. Поэтому они архивируются в область архива WAL так же, как и файлы сегментов WAL. Файлы истории - это просто небольшие текстовые файлы, поэтому их долго хранить недорого (в отличие от больших файлов сегментов). Если хотите, вы можете добавить комментарии в файл истории, чтобы записать свои собственные заметки о том, как и почему была создана эта конкретная временная шкала. Такие комментарии будут особенно полезны, когда у вас есть множество разных временных шкал в результате экспериментов.

Сохраняется стандартное поведение восстановления до последней найденной временной линии в архиве. Если нужно восстановиться до временной линии, которая была актуальной на момент создания базовой резервной копии или в конкретную дочернюю временную линию (то есть, нужно вернуться к состоянию, которое было сгенерировано после попытки восстановления), необходимо указать current или идентификатор целевой временной линии в recovery_target_timeline. Вы не можете восстановиться во временные линии, которые отклонились раньше базовой резервной копии.

25.3.6. Советы и примеры

Ниже приведены некоторые советы по настройке непрерывного архивирования.

25.3.6.1. Отдельные горячие резервные копии

Возможно использовать средства резервного копирования Tantor SE для создания автономных горячих резервных копий. Это резервные копии, которые нельзя использовать для восстановления в определенный момент времени, но обычно они гораздо быстрее резервного копирования и восстановления, чем дампы pg_dump. (Они также гораздо больше, чем дампы pg_dump, поэтому в некоторых случаях преимущество в скорости может быть уменьшено).

Как и в случае с базовыми резервными копиями, самым простым способом создания автономной горячей резервной копии является использование инструмента pg_basebackup. Если вы включите параметр -X при его вызове, все журналы предварительной записи, необходимые для использования резервной копии, будут автоматически включены в резервную копию, и для восстановления резервной копии не требуется никаких дополнительных действий.

25.3.6.2. Сжатые архивные журналы

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

archive_command = 'gzip < %p > /mnt/server/archivedir/%f.gz'

Вы затем должны использовать gunzip во время восстановления.

restore_command = 'gunzip < /mnt/server/archivedir/%f.gz > %p'

25.3.6.3. archive_command Скрипты

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

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

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

Примеры требований, которые могут быть решены в рамках сценария, включают:

  • Копирование данных на безопасное удаленное хранилище данных

  • Группировка файлов журнала предзаписи таким образом, чтобы они передавались каждые три часа, а не по одному

  • Взаимодействие с другими программными средствами резервного копирования и восстановления

  • Взаимодействие с программным обеспечением мониторинга для отчетности об ошибках

Подсказка

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

25.3.7. Ограничения в использовании

На данный момент существуют несколько ограничений техники непрерывного архивирования. Вероятно, они будут исправлены в будущих версиях:

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

  • Ссылка на команду CREATE TABLESPACE команды записываются в WAL-журнал с абсолютным путем, и поэтому будут воспроизведены как создание таблицы с тем же абсолютным путем. Это может быть нежелательным, если журнал воспроизводится на другой машине. Это может быть опасным, даже если журнал воспроизводится на той же машине, но в новом каталоге данных: воспроизведение все равно перезапишет содержимое исходного табличнoго пространства. Чтобы избежать потенциальных проблем такого рода, лучшей практикой является создание нового базового резервного копирования после создания или удаления табличных пространств.

Также следует отметить, что формат по умолчанию WAL довольно громоздкий, так как он включает множество снимков дисковых страниц. Эти снимки страниц предназначены для поддержки восстановления после сбоя, поскольку нам может потребоваться исправить частично записанные дисковые страницы. В зависимости от аппаратного и программного обеспечения вашей системы риск частичных записей может быть достаточно мал, чтобы его можно было игнорировать. В этом случае вы можете значительно сократить общий объем архивных журналов, отключив снимки страниц с помощью параметра full_page_writes. (Прочитайте заметки и предупреждения в разделе Глава 29 перед этим). Отключение снимков страниц не мешает использованию журналов для операций восстановления в точку во времени (PITR). Одной из областей для будущего развития является сжатие архивных данных WAL путем удаления ненужных копий страниц, даже если full_page_writes включен. В промежутке администраторы могут пожелать сократить количество включенных в WAL снимков страниц, увеличив интервалы контрольных точек настолько, насколько это возможно.