Страницы

Сохранить статью у себя в соцсети:

вторник, 14 мая 2013 г.

§ PostgreSQL backup and recovery.

PostgreSQL: резервное копирование с минимальным временем восстановления

postgres backup and recovery
Предположим что у нас есть кластер postgresql работающий в режиме потоковой репликации. Есть master-сервер и горячий hot-standby готовый в любой момент стать полноценным мастером. Таким образом у нас реализована отказоустойчивая связка, в которой в случае выхода из строя мастера, горячий hot-stnadby заменить погибшего товарища. При плохом развитии событий, нам остается только создать trigger-файл и переключить наши приложения на работу с новым мастером. И стало все хорошо.
Известно что природа потоковой репликации устроена так, что изменения прошедшие в мастере, должны оказаться на подчиненном узле как можно быстрее. Выходит что, подчиненный узел представляет собой (почти полную) копию мастера. Это очень хорошо в случае немедленного восстановления на момент предшествующий сбою.  Однако, возможны ситуации когда вполне легитимные изменения были сделаны на стороне приложения и попали как на мастер, так и на подчиненный сервер. Например, были удалены/изменены данные в части таблиц или же таблицы были вовсе удалены. С точки зрения базы данных ничего фатального не произошло, а с точки зрения бизнеса - произошла катастрофа. В таком случае провозглашение горячего hot-standby в мастера, процедура явно бесполезная... 
И тут возникает резонный вопрос, а как же резервные копии? Есть как минимум два варианта:
  • использовать периодическое резервное копирование средствами pg_dump;
  • использовать резервное копирование на основе базовых копий и архивов WAL.
Первый способ достаточно прост в реализации и требует минимум усилий по установке и сопровождению. Однако этот вариант не предлагает восстановить каталог базы данных на момент предшествующий сбою. Второй вариант сложней и затратней в плане хранения, но этот вариант является гораздо эффективным средством в случае восстановления. О нем как раз и пойдет речь.
Плюсы:
  • возможность восстановить кластер базы на любой момент времени относительно времени создания базовой копии и времени сбоя; 
  • в качестве условия для восстановления может служить как временная отметка так и конкретная транзакция.
Минусы:
  • базовая копия занимает приблизительный размер кластера базы данных;
  • необходимость хранения WAL-архивов за период хранения базовой копии.
Таким образом этот способ резервного копирования предлагает гибкие возможности по восстановлению, но в то же время добавляет значительные требования к хранению резервных копий.

Итак поехали... По ходу действия нужно ответить на несколько вопросов:
Первый вопрос, это где будет храниться базовая копия? Базовая копия будет создаваться на мастере. Самая свежая копия, также будет храниться на мастере. При необходимости базовые копии прошедших дней и соответствующие им архивы можно "увозить" на hot-standby. Такой выбор основан на следующих выводах:
  • в случае "бизнес-катастрофы", мы сможем запустить процедуру восстановления на этом же сервере, не привлекая другие мощности и не запуская процесса копирования с backup-серверов;
  • в случае аппаратного сбоя, мы сможем запустить мастер из нашего hot-standby, не прибегая к резервным копиям.
Где будут храниться WAL-архивы? WAL-архивы, также нужно хранить поближе к базовой резервной копии чтобы исключить вариант их копирования по сети в случае необходимости восстановления. Таким образом, выходит что, самая свежая резервная копия должна лежать там где она будет восстановлена в рабочую копию в случае аварии. Ответив на вопросы можно приступить к реализации через следующий алгоритм:
  • настройка режима архивирования WAL-логов;
  • настройка резервного копирования (pg_basebackup);
  • хранение одной или более резервных копий;
  • удаление самой старой резервной копии в случае успешного выполнения п.1;
  • удаление соответствующих WAL-архивов от резервной копии из п.3;
  • опционально можно проводить процедуру проверки резервных копий на предмет их "профпригодности".
Режим архивирования WAL-логов настраивается через включение параметров archive_mode и archive_command в postgresql.conf и создание директории где будут храниться архивы. Для начала стоит включить режим архивирования и оценить объем архивов создаваемых за одни сутки работы базы данных. Это позволит провести оценку требуемого места для хранения архивов и базовых копий.
# vi /etc/postgresql-9.2/postgresql.conf
archive_mode = on
archive_command = 'cp %p /opt/pgsql/pgbackup/archive/%f'

Непосредственное резервное копирование настраиваем средствами pg_basebackup. Это программа из комплекта утилит идущих вместе с PostgreSQL которую можно использовать как для настройки потоковой репликации, так и для снятия резервных копий. Принцип работы позволяет снимать резервную копию не останавливая кластер базы данных. Исходя из задачи, нам всего лишь нужно запускать pg_basebackup по расписанию в cron. Учитывая требования по месту, нужно позаботиться о достаточном месте на диске, во избежание переполнения.

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

После завершения создания резервной копии, старую копию можно удалить вместе с архивами. Удаление архивов выполняется с помощью утилиты pg_archivecleanup. Утилита позволяет аккуратно удалить ненужные архивы основываясь на специальных файлах-метках, которые создаются при резервном копировании. 

Также немаловажно настроить процедуру проверки резервной копии после её создания. Алгоритм достаточно простой: нужно скопировать базовую копию в некий каталог-песочницу (осторожно, место!), создать в ней минимально необходимые файлы конфигурации необходимые для запуска в режиме восстановления и запустить postgres относительно этого каталога-песочницы, после запуска необходимо проанализировать лог и сделать вывод является ли резервная копия пригодной для восстановления. 
Таким образом процесс укладывается в три шага: создание базовой копии, её проверка и    удаление старой, предыдущей базовой копии.

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

Вот и все, процедура восстановления завершена. Ну и очевидным является то, что изменения совершенные после момента аварии будут утеряны. Разве что они будут доступны в скопированном ранее битом кластере. Можно запустить еще один postgres относительно этого каталога и скопировать необходимые данные.

На практике, в моем случае, все выглядит следующим образом. Есть два скрипта, clonepg.sh который делает резервную копию, чистит старые копии и архивы, при необходимости запускает проверку резервной копии. Второй скрипт basebackup-validation.sh осуществляет проверку базовой копии и рапортует по результату. Для работы требуется указать выполнение скрипта clonepg.sh в crontab пользователя postgres. В качестве параметров нужно передать путь хранения резервных копий, опциональный параметр --validate и почтовые адреса для отправки результата проверки. Также подразумевается что пользователь postgres может выполнять подключение к кластеру базы данных.
# su - postgres
$ mkdir bin
$ mv clonepg.sh bin/
$ mv basebackup-validation.sh bin/
$ clonepg.sh -b=/opt/pgbackup -v=/opt/pgbackup/sandbox -m=lesovsky@gmail.com

Также возможно отдельное создание базовой копии и отдельный запуск проверки резервной копии.

$ clonepg.sh --backupdir=/opt/pgbackup 
$ basebackup-validation.sh --target=/opt/pgbackup/db-05-09-2013 \
--sandbox=/opt/pgbackup/sandbox \
--mailto=lesovsky@gmail.com,blablabla@trashmail.com

Скрипты резервного копирования и валидации можно взять здесь.

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

На главную "Virtualizing Linux"

4 комментария:

  1. Есть уже готовое решение под названием barman.
    В общем, схема очень проста, например, раз в неделю делаем полную копию базы с помощью pgdump, а потом делаем инкрементные копии раз в день.

    ОтветитьУдалить
    Ответы
    1. Да, я в курсе, очень хороший инструмент от авторитетных постгресовых деятелей.

      Удалить
  2. Добрый день!

    Что вы скажите об https://github.com/ossc-db/pg_rman.

    ОтветитьУдалить
    Ответы
    1. Добрый день! Не пробовал, но судя по описанию почти что тоже самое делает и pg_basebackup (за исключением рестора).

      Удалить

Популярные сообщения

Профиль в Google+ Яндекс цитирования Яндекс.Метрика