barbitoff programmer`s blog

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

среда, 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).


вторник, 28 августа 2012 г.

Debian: скачивание папок по ftp

Возникла необходимость бэкапить несколько папок с одного сервера на другой, получая их по ftp (на обоих серверах - Debian). Написать соответствующий bash-скрипт не составило труда, возник лишь вопрос с выбором утилиты для собственно скачки папок по ftp. Первой идеей был wget, умеющий и работать с ftp, и рекурсивно выкачивать директории:
wget -r "ftp://user@password:host"
Но тут камнем преткновения стал русский язык в именах скачиваемых файлов и папок: независимо от наличия / отсутствия поддержки iri папки и файлы с русскими именами успешно скачивались, вот только сохранялись с побитыми именами (приведен фрагмент лога wget`а):
--2012-08-27 11:24:14--  ftp://login:passorw@host/dir/%D0%BD%D0%B5%D1%82%20%D0%B2%20%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B5/file.doc
           => « host/dir/не\321%82 в \321%81пи\321%81ке/ file.doc»
(в оригинале должно было быть "нет в списке"), т.е. часть русских символов оставалась URL-кодированной. При этом на сервере используется UTF-8, и другие клиенты скачивают файлы без проблем.
В результате от wget я отказался в пользу lftp. В нем скачка директории выполняется так:
lftp -e 'mirror -e dir /path/to/download_dir/ bye;' -u user,password host
Здесь "dir" - папка на ftp-сервере,  /path/to/download_dir/ - путь для сохранения скачанной папки.