Резервное копирование и восстановление

Как и все, что содержит ценные данные, базы данных QHB должны регулярно подвергаться резервному копированию. Существует три принципиально разных подхода к резервному копированию данных QHB:

У каждого есть свои сильные и слабые стороны, которые обсуждается в следующих разделах.

SQL-дамп

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

qhb_dump dbname > dumpfile

qhb_dump записывает свой результат в стандартный вывод. Ниже мы увидим, когда это может быть полезно. В то время как вышеуказанная команда создаёт текстовый файл, qhb_dump может создавать файлы в других форматах, которые обеспечивают параллелизм и более детальный контроль над восстановлением объектов.

qhb_dump — это обычное клиентское приложение QHB. Это означает, что можно выполнить процедуру резервного копирования с любого удалённого хоста, который имеет доступ к базе данных. Но помните, что qhb_dump не работает с использованием специальных привилегий. В частности, требуется доступ на чтение ко всем таблицам, для которых выполняется резервное копирование, поэтому для резервного копирования всей базы данных почти всегда требуется запуск с правами суперпользователя базы данных.

Заметка
Если у вас недостаточно прав для резервного копирования всей базы данных, вы всё равно можете создавать резервные копии тех частей базы данных, к которым у вас есть доступ, используя такие параметры, как -n schema или -t table).

Чтобы указать, к какому серверу баз данных должен обращаться qhb_dump, используйте параметры командной строки -h host и -p port. Хост по умолчанию — это локальный хост или то значение, которое указано в переменной среды PGHOST. Точно так же порт по умолчанию указывается переменной окружения PGPORT или, если она не задана, значением, принятым по умолчанию.

Заметка
При компиляции сервер обычно имеет те же значения параметров по умолчанию

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

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

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

Заметка
Исключением являются те операции, которым требуется полная блокировка, например, большинство форм ALTER TABLE.

Восстановление дампа

Текстовые файлы, созданные qhb_dump, предназначены для чтения программой qsql. Общая форма команды для восстановления дампа:

qsql dbname < dumpfile

где dumpfile — это файл, содержащий вывод команды qhb_dump. Эта команда не будет создавать базу данных dbname, поэтому вы должны создать её самостоятельно из template0 перед выполнением qsql (например, с помощью createdb -T template0 dbname). qsql поддерживает параметры, аналогичные qhb_dump, для указания сервера базы данных, к которому нужно подключиться, и имени пользователя для использования (см. подробнее в qsql). Дампы нетекстовых файлов восстанавливаются с помощью утилиты qhb_restore.

Перед восстановлением дампа SQL все пользователи, которым принадлежали объекты или права на них в выгруженной базе данных, уже должны существовать. Если их нет, при восстановлении не удастся воссоздать объекты с первоначальным владельцем и / или правами. (Иногда это желаемое поведение, но обычно это не так).

По умолчанию сценарий qsql будет продолжать выполняться после возникновения ошибки SQL. Если запустить qsql с переменной ON_ERROR_STOP установленной для изменения этого поведения, то qsql завершится кодом 3, если возникает ошибка SQL:

qsql --set ON_ERROR_STOP=on dbname < dumpfile

В любом случае, у вас будет только частично восстановленная база данных. В качестве альтернативы вы можете указать, что весь дамп должен быть восстановлен за одну транзакцию, поэтому восстановление будет либо полностью завершено, либо полностью отменено. Этот режим может быть указан путём передачи параметров командной строки -1 или --single-transaction в qsql. При использовании этого режима помните, что даже небольшая ошибка может послужить причиной отката восстановления, которое уже выполняется в течение многих часов. Однако это все же может быть предпочтительнее, чем ручная очистка сложной базы данных после частично восстановленного дампа.

Возможность qhb_dump и qsql использовать каналы ввода/вывода позволяет скопировать базу данных напрямую с одного сервера на другой, например:

qhb_dump -h host1 dbname | qsql -h host2 dbname

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

После восстановления резервной копии целесообразно запустить ANALYZE для каждой базы данных, чтобы оптимизатор запросов имел полезную статистику. См. раздел Обновление статистики планировщика и раздел Процесс «Автовакуум» для получения дополнительной информации. Дополнительные советы о том, как эффективно загружать большие объёмы данных в QHB, см. в разделе Заполнение базы данных.

Использование qhb_dumpall

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

qhb_dumpall > dumpfile

Полученный дамп можно восстановить с помощью qsql:

qsql -f dumpfile qhb

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

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

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

Данные всего экземпляра могут быть выгружены отдельно, используя опцию --globals-only. Это необходимо для полного резервного копирования экземпляра при выполнении команды qhb_dump в отдельных базах данных.

Обработка больших баз данных

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

Используйте сжатые дампы. Вы можете использовать вашу предпочитаемую программу сжатия, например, gzip:

qhb_dump dbname | gzip > filename.gz

Восстановление дампа с помощью:

gunzip -c filename.gz | qsql dbname

или:

cat filename.gz | gunzip | qsql dbname

Команда split позволяет разбить вывод на более мелкие файлы, приемлемые по размеру для базовой файловой системы. Например, чтобы сделать куски по 1 мегабайту:

qhb_dump dbname | split -b 1m - filename

Восстановление дампа с помощью:

cat filename* | qsql dbname

Используйте специальный формат дампа qhb_dump. Если QHB был собран в системе с установленной библиотекой сжатия zlib, пользовательский формат дампа будет сжимать данные по мере их записи в выходной файл. Это приведет к размеру файла дампа, аналогичному использованию gzip, но у него есть дополнительное преимущество: таблицы могут восстанавливаться выборочно. Следующая команда создаёт дамп базы данных с использованием специального формата дампа:

qhb_dump -Fc dbname > filename

Дамп специального формата не является сценарием для qsql, а должен быть восстановлен с помощью qhb_restore, например:

qhb_restore -d dbname filename

Для очень больших баз данных вам может потребоваться объединить split с одним из двух других подходов.

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

qhb_dump -j num -F d -f out.dir dbname

Вы можете использовать qhb_restore -j для параллельного восстановления дампа. Это будет работать для любого архива, созданном в специальном формате или в формате каталога, независимо от того, был ли он создан с помощью qhb_dump -j.

Резервное копирование на уровне файловой системы

Альтернативная стратегия резервного копирования заключается в прямом копировании файлов, которые QHB использует для хранения данных в базе данных; Вы можете использовать любой метод для резервного копирования файловой системы; например:

tar -cf backup.tar /usr/local/qhb/data

Однако есть два ограничения, которые делают этот метод непрактичным или, по крайней мере, уступают методу qhb_dump:

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

  2. Если вы вникли в детали структуры файловой системы базы данных, у вас может возникнуть соблазн попытаться выполнить резервное копирование или восстановление только определенных отдельных таблиц или баз данных из их соответствующих файлов или каталогов. Это не будет работать, потому что информация, содержащаяся в этих файлах, не может быть использована без файлов журнала транзакций pg_xact/*, которые содержат статус фиксации всех транзакций. Файл таблицы может использоваться только с этой информацией. Конечно, также невозможно восстановить только таблицу и связанные с pg_xact данные, потому что это сделает все остальные таблицы в экземпляре базы данных бесполезными. Таким образом, резервные копии файловой системы работают только для полного резервного копирования и восстановления всего экземпляра базы данных.

Альтернативный подход к резервному копированию файловой системы заключается в создании «согласованного снимка» каталога данных, если файловая система поддерживает эту функцию (и вы уверены, что она реализована правильно). Типичная процедура - сделать «замороженный снимок» тома, содержащего базу данных, затем скопировать весь каталог данных (не только части, см. выше) из моментального снимка на устройство резервного копирования, а затем освободить замороженный снимок. Это будет работать даже во время работы сервера базы данных. Однако созданная таким образом резервная копия сохраняет файлы базы данных в таком состоянии, как если бы сервер базы данных был неправильно остановлен; поэтому, когда вы запускаете сервер базы данных с резервной копией данных, он будет считать, что предыдущий экземпляр сервера завершился аварийно, и применит данные журналов WAL. Это не проблема, однако это стоит иметь в виду.

Внимание!!!
Обязательно включите файлы WAL в свою резервную копию!

Заметка
Вы можете выполнить CHECKPOINT перед созданием снимка, чтобы сократить время восстановления.

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

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

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

Обратите внимание, что резервная копия файловой системы обычно больше, чем дамп SQL. (Например, qhb_dump не нужно записывать содержимое индексов, только команды для их восстановления). Однако создание резервной копии файловой системы может выполняться быстрее.

Непрерывное архивирование и восстановление на момент времени

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

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

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

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

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

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

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

Для успешного восстановления с использованием непрерывного архивирования (также называемого «оперативным резервным копированием» многими разработчиками баз данных) нужна непрерывная последовательность архивированных WAL-файлов история которой, по крайней мере, начинается со времени начала резервного копирования. Итак, для начала необходимо настроить и протестировать процедуру архивации файлов WAL, прежде чем делать первую базовую резервную копию. Соответственно, сначала рассмотрим механизм архивирования файлов WAL.

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

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

При архивировании данных WAL нам нужно захватить содержимое каждого файла сегмента после его заполнения и сохранить эти данные где-то перед тем, как файл сегмента будет повторно использован. В зависимости от приложения и доступного оборудования, может быть много разных способов «сохранения данных где-то»: мы можем скопировать файлы сегментов в каталог, смонтированный NFS на другом компьютере, записать на ленточный накопитель (гарантируя, что у вас есть способ идентификации исходного имени каждого файла), или собрать вместе и записать на компакт-диски, или что-то ещё. Чтобы предоставить администратору базы данных гибкость, QHB старается не делать никаких предположений о том, как будет осуществляться архивирование. Вместо этого QHB позволяет администратору указать команду оболочки, которая будет выполняться, чтобы скопировать заполненный файл сегмента туда, куда он должен попасть. Команда может быть такой же простой, как cp, или может вызывать сложный сценарий оболочки - все зависит от администратора.

Чтобы включить архивирование WAL, установите для параметра конфигурации wal_level значение replica или выше, для параметра archive_mode - значение on и укажите команду оболочки для использования в параметре конфигурации archive_command. На практике эти настройки всегда будут помещаться в файл qhb.conf. В archive_command %p заменяется путём к файлу для архивирования, а %f заменяется только именем файла. (Путь указывается относительно текущего рабочего каталога, т. е. каталога данных экземпляра). Используйте %% если вам нужно вставить символ % в команду. Самая простая полезная команда выглядит примерно так:

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'  # Unix

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

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

Аналогичная команда будет сгенерирована для каждого нового файла, подлежащего архивированию.

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

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

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

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

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

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

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

Обратите внимание, что несмотря на то, что архивация WAL позволит вам восстановить любые изменения, внесенные в данные в вашей базе данных QHB, она не восстановит изменения, внесённые в файлы конфигурации (то есть qhb.conf, qhb_hba.conf и qhb_ident.conf), так как они редактируются вручную, а не с помощью операций SQL. Возможно, вы захотите сохранить файлы конфигурации в том же месте, где будут храниться результаты ваших обычных процедур резервного копирования файловой системы. расположение файлов

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

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

Таблица 1. Функции управления резервным копированием

ИмяТип ответаОписание
pg_create_restore_point(name text)pg_lsnСоздать именованную точку для выполнения восстановления*
pg_current_wal_flush_lsn()pg_lsnПолучить текущее местоположение сброса журнала предзаписи.
pg_current_wal_insert_lsn()pg_lsnПолучить текущее местоположение вставки журнала предзаписи.
pg_current_wal_lsn()pg_lsnПолучить текущее местоположение записи в журнал предзаписи.
pg_start_backup(label text [, fast boolean [, exclusive boolean ] ])pg_lsnПодготовление к выполнению резервному копированию*
pg_stop_backup()pg_lsnЗавершить выполнение монопольного резервного копирования*
pg_stop_backup(exclusive boolean [, wait_for_archive boolean ])set of recordЗавершить выполнение монопольного резервного копирования*
pg_is_in_backup()boolИстинно, если монопольное резервное копирование все еще выполняется.
pg_backup_start_time()timestamp with time zoneПолучить время запуска монопольного резервного копирования.
pg_switch_wal()pg_lsnПринудительное переключение на новый файл журнала с опережением записи*
pg_walfile_name(lsn pg_lsn)textПреобразовать местоположение журнала предзаписи в имя файла.
pg_walfile_name_offset(lsn pg_lsn)text, integerПреобразовать местоположение журнала предзаписи в имя файла и десятичное смещение байта в нём.
pg_wal_lsn_diff(lsn pg_lsn, lsn pg_lsn)numericРассчитать разницу между двумя местоположениями журнала записи.

Заметка
* - (по умолчанию ограничено суперпользователями, но другим пользователям может быть предоставлено разрешение EXECUTE для запуска функции).

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

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

Самый простой способ выполнить базовое резервное копирование - использовать инструмент qhb_basebackup. Он может создавать базовую резервную копию в виде обычных файлов или в виде архива tar. Альтернативой этому инструменту служит qbackup. Эта программа позволяет сохранять ваши резервные копии в структурированный каталог, при этом поддерживается инкрементальное копирование и сжатие, а также параллельный режим работы.

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

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

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

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

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

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

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

Резервные копии низкого уровня могут быть сделаны немонопольным способом.

Создание немонопольной резервной копии на низком уровне

Немонопольное резервное копирование низкого уровня позволяет запускать другие параллельные резервные копии (через API-интерфейс или qhb_basebackup).

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

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

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

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

    По умолчанию pg_start_backup может занять много времени до завершения. Это связано с тем, что он выполняет контрольную точку, а операции ввода-вывода, требуемые для этого, распределяются в интервале времени, равного по умолчанию половине вашего интервала между контрольными точками (см. параметр конфигурации checkpoint_completion_target в разделе Контрольные точки). Обычно это то, что и требуется, потому что это минимизирует влияние на обработку запросов. Если вы хотите начать резервное копирование как можно скорее, измените второй параметр на true, который немедленно выдаст контрольную точку с использованием максимально возможного количества операций ввода-вывода.

    Третий параметр false указывает pg_start_backup инициировать немонопольную базовую резервную копию.

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

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

    SELECT * FROM pg_stop_backup(false, true);

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

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

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

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

Создание монопольной резервной копии на низком уровне

Заметка
Монопольный метод резервного копирования устарел и обычно его следует избегать.

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

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

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

    SELECT pg_start_backup('label');

    где label - любая строка, которую вы хотите использовать для уникальной идентификации этой операции резервного копирования. pg_start_backup создает файл метки резервной копии с именем backup_label в каталоге кластера с информацией о вашей резервной копии, включая время начала и строку метки. Функция также создает файл карты табличных пространств, называемый tablespace_map , в каталоге кластера с информацией о символических ссылках табличных пространств в pg_tblspc/, если присутствует одна или несколько таких ссылок. Оба файла имеют решающее значение для целостности резервной копии, если вам необходимо восстановить базу из нее.

    По умолчанию вызов pg_start_backup может занять довольно продолжительное время. Это связано с тем, что при этом выполняется контрольная точка, и ввод-вывод, необходимый для выполнения контрольной точки, будет распределен в течение значительного периода времени, по умолчанию в течение половины установленного интервала между контрольными точками (см. параметр конфигурации checkpoint_completion_target в разделе Контрольные точки). Обычно это то, что требуется, так как это минимизирует влияние на обработку запросов. Если вы хотите начать резервное копирование как можно скорее, используйте:

    SELECT pg_start_backup ('label', true);

    Это заставляет контрольную точку выполниться как можно быстрее.

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

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

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

    SELECT pg_stop_backup();

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

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

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

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

Некоторые инструменты резервного копирования файловой системы выдают предупреждения или ошибки, если файлы, которые они пытаются скопировать, изменяются в процессе копирования. При создании базовой резервной копии активной базы данных это нормальная ситуация, а не ошибка. Однако вы должны убедиться, что вы можете отличить логи такого рода от реальных ошибок. Например, некоторые версии rsync возвращают отдельный код завершения для «исчезнувших исходных файлов», и вы можете написать скрипт, чтобы принять этот код завершения как случай, не связанный с ошибкой. Кроме того, некоторые версии GNU tar возвращают код ошибки, неотличимый от фатальной ошибки, если файл был усечён во время его копирования через tar. К счастью, GNU tar версии 1.16 и выше завершается с кодом 1, если файл был изменен во время резервного копирования, и 2 для других ошибок.

Заметка
В GNU tar версии 1.23 и более поздних версиях вы можете использовать параметры предупреждений --warning=no-file-changed, --warning=no-file-removed, чтобы скрыть соответствующие предупреждающие сообщения.

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

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

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

Содержимое каталогов pg_dynshmem/, pg_notify/, pg_serial/, pg_snapshots/, pg_stat_tmp/ и pg_subtrans/ (но не сами каталоги) может быть исключено из резервной копии, поскольку оно будет инициализировано при запуске qhbmaster. Если stats_temp_directory (см. Статистика выполнения) установлен и указывает на подкаталог внутри каталога данных, то содержимое этого каталога также может быть опущено.

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

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

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

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

Восстановление с помощью непрерывного архива

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

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

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

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

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

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

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

  7. Задайте параметры конфигурации восстановления в qhb.conf и создайте файл recovery.signal в каталоге данных экземпляра. Вы также можете временно изменить qhb_hba.conf, чтобы обычные пользователи не могли подключаться, пока вы не убедитесь, что восстановление прошло успешно.

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

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

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

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

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

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

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

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

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

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

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

Заметка
В команде restore в qbackup существуют опции, позволяющие выбрать эти настройки. Ими можно будет воспользоваться только если резервная копия была сделана при помощи backup

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

Линии времени

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

Чтобы справиться с этой проблемой, в QHB есть понятие линия времени. Всякий раз, когда восстановление архива завершается, создаётся новая временная линия для определения последовательности записей WAL, созданной после этого восстановления. Идентификационный номер линии времени является частью имён файлов сегментов WAL, поэтому новая линия времени не перезаписывает данные WAL, созданные предыдущими линиями времени. Фактически возможно архивировать много различных линий времени. Хотя это может показаться бесполезной функцией, это часто помогает. Рассмотрим ситуацию, когда вы не совсем уверены, к какому моменту времени необходимо восстанавливаться, и поэтому вам приходится делать несколько попыток восстановления на определенный момент времени методом проб и ошибок, пока не найдется лучшее место для ветвления из старой истории. Без линий времени этот процесс быстро приведет к неуправляемому беспорядку. С помощью линий времени вы можете восстановить любое предыдущее состояние, в том числе состояния в ветвях линий времени, от которых вы отказались ранее.

Каждый раз, когда создаётся новая линия времени, QHB создаёт файл «истории линии времени», который показывает, с какой линии времени он вышел и когда. Эти файлы истории необходимы для того, чтобы система могла выбрать правильные файлы сегментов WAL при восстановлении из архива, который содержит несколько линий времени. Поэтому они архивируются в область архивирования WAL, как и файлы сегментов WAL. Файлы истории — это просто небольшие текстовые файлы, поэтому их целесообразно хранить на протяжении долгого времени (в отличие от больших файлов сегментов). Вы можете, если хотите, добавлять комментарии в файлы истории, чтобы записывать свои собственные заметки о том, как и почему была создана эта конкретная линия времени. Такие комментарии будут особенно полезны, когда в результате экспериментов у вас будет череда различных линий времени.

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

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

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

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

Автономные горячие резервные копии

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

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

Если требуется больше гибкости при копировании файлов резервных копий, процесс более низкого уровня можно использовать и для автономных оперативных резервных копий. Чтобы подготовиться к низкоуровневым автономным горячим резервным копиям, убедитесь, что для wal_level задано значение replica или выше, для параметра archive_mode значение on, и настройте команду archive_command которая выполняет архивирование только при наличии файла переключателя. Например:

archive_command = 'test ! -f /var/lib/qhb/backup_in_progress || (test ! -f /var/lib/qhb/archive/%f && cp %p /var/lib/qhb/archive/%f)'

Заметка
В qbackup есть подкоманда backup-wal, которую можно использовать для этих целей см. подробнее в qbackup backup-wal

Эта команда выполняет архивирование, когда существует /var/lib/qhb/backup_in_progress, и в противном случае молча возвращает нулевое состояние выхода (что позволяет QHB переиспользовать ненужный файл WAL).

С помощью этой подготовки можно сделать резервную копию с помощью сценария, подобного следующему:

touch /var/lib/qhb/backup_in_progress
qsql -c "select pg_start_backup('hot_backup');"
tar -cf /var/lib/qhb/backup.tar /var/lib/qhb/data/
qsql -c "select pg_stop_backup();"
rm /var/lib/qhb/backup_in_progress
tar -rf /var/lib/qhb/backup.tar /var/lib/qhb/archive/

Файл-переключатель /var/lib/qhb/backup_in_progress создаётся первым, что позволяет архивировать заполненные файлы WAL. После резервного копирования файл переключателя удаляется. Архивные файлы WAL затем добавляются в резервную копию, чтобы как базовая резервная копия, так и все необходимые файлы WAL были частью одного и того же tar-файла. Пожалуйста, не забудьте добавить обработку ошибок в ваши скрипты резервного копирования.

Существует альтернативный подход к горячему резервному копированию в виде утилиты qbackup. Эта утилита комбинирует архивирование WAL-записей и постраничное инкрементальное резервное копирование, что позволяет добиться более компактных резервных копий за счёт сохранения только тех данных, которые изменились с момента предыдущей автономной резервной копии.

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

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

archive_command = 'gzip < %p > /var/lib/qhb/archive/%f'

Затем вам нужно будет использовать gunzip во время восстановления:

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

Скрипты archive_command

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

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

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

Примеры задач, которые могут быть решены в сценарии:

  • Копирование данных для безопасного хранения данных за пределами площадки.

  • Пакетное копирование WAL, так что они передаются каждые три часа, а не по одному.

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

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

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

Заметка
Вы можете использовать qbackup backup-wal для этих целей.

Предостережения

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

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

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

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