barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

среда, 29 августа 2012 г.

PostgreSQL: бэкапы больших БД

Самая простая идея бэкапов PostgreSQL - это pg_dump, вызываемый cron`ом. Где такой подход крайней неэффективен и порой даже вообще неприменим - так это при больших объемах БД, особенно, если БД изменяется редко. В таких случаях мы будем получать большое количество увесистых, но практически идентичных бэкапов.
Благо разработчики постгреса подумали над этим вопросом, и предусмотрели возможность "разностных" бэкапов БД (точнее, бэкапится не одна БД, а кластер целиком). В данном случае имеется "базовый" бэкап кластера, и множество мелких бэкапов, содержищих лишь измененные данные. В качестве этих минибэкапов выступают "write ahead" логи (WAL).
Исчерпывающее описание процесса настройки приведено на сайте postgresql (http://www.postgresql.org/docs/8.4/static/continuous-archiving.html), я приведу лишь небольшой пример (используется PostgreSQL 8.4 на Debian Squeeze):
1) Во-первых, необходимо включить архивацию WAL и задать команду, которая будет вызываться каждый раз, когда postgres закончил очередной WAL-файл и его можно архивировать. В моем случае каждый WAL-файл архивируется 7z-ом и кладется в /backup/WAL-archive/ (перед этим проверяется, что файл ещё не существует, как рекомендовано в доках постгреса). Ниже приведен фрагмент конфигурации кластера:
# - Archiving -
archive_mode = on
archive_command = 'test ! -f /backup/WAL-archive/%f.7z && 7zr a /backup/WAL-archive/%f %p'
#archive_timeout = 0 
2) Перезапускаем postgres
3) Если все ок, через некоторое время в /backup/WAL-archive/ начнут появляться файлы архивов
4) Теперь нужно выполнить базовый бэкап кластера. Для начала, сообщаем серверу, что начался бэкап, выполняя следующий SQL-запрос:
SELECT pg_start_backup('backup')
Параметр SQL-функции pg_start_backup является лишь меткой, его значение не принципиально.
Затем, выполняем собственно базовый бэкап директории данных кластера:
tar c --exclude='pg_xlog/*' -C /var/lib/postgresql/8.4/ myclaster | 7zr a -si /backup/base-archive/base.tar.7z
В данном случае директория данных моего кластера размещена в /var/lib/postgresql/8.4/myclaster, а tar.7z архив будет сложен в /backup/base-archive/. Содержимое директории WAL-логов исключается их копии, т.к. WAL`ы архивируются отдельно.
Теперь можно сообщить серверу, что бэкап закончен, запросом:
SELECT pg_stop_backup();
Сервер заархивирует все созданные за время бэкапа WAL`ы, а также ещё один файл с расширением "backup". Его имя будет указывать на тот WAL-файл, начиная с которого данные не попали в бэкап. Все WAL-файлы до него можно удалять, т.к. они  относятся к изменениям, уже присутствующим в только что созданном базовом бэкапе.

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


Комментариев нет:

Отправить комментарий