10 способов сделать резервную копию в PostgreSQL
> SQL > PostrgeSQLДата обновления: 30 мая 2025 г. Дата публикации: 23 мая 2024 г. Автор: Стрекаловский Александр
Многие разговоры про бэкапы начинаются с присказки, что люди делятся на две категории…
так вот я отношусь к тем людям, которые делают бэкапы.
Правильно настроенное резервное копирование и проверка резервных копий укрепляет сон. А наличие заранее написанных и отработанных инструкций по восстановлению вообще укрепляет пищеварение и иммунитет.
Так вот, за время работы с PostgreSQL мне довелось часто настраивать резервное копирование. При этом условия и требования были самые разные. Однако набор инструментов, за редким исключением, оставался неизменным.
В этой статье я поделюсь своим опытом в деле, как можно делать резервные копии PostgreSQL.
Если рассматривать резервное копирование как вполне конкретный процесс, то возникает два простых вопроса:
1. откуда запускать резервное копирование?
2. какие инструменты следует использовать для резервного копирования?
На первый вопрос есть два варианта ответа: * Можно запускать задачу резервного копирования с выделенного backup сервера. На мой взгляд это наиболее подходящий вариант. * Либо запускать задачу непосредственно с сервера БД, это в случае если нет выделенного сервера бэкапов.
С инструментами все гораздо интереснее.
Здесь я выделяю две группы: основные инструменты и вспомогательные.
* Основные — это те, которые собственно и выполняют резервное копирование.
* Вспомогательные — это те, которые добавляют что-то особенное к процессу резервного копирования. Например, архивирование, шифрование, управление нагрузкой и т.д.
В комплекте PostgreSQL есть 2 утилиты которые позволяют делать резервные копии.
Это pg_dump/pg_dumpall и pg_basebackup.
Кроме того, есть возможность использовать утилиты файлового копирования, такие как rsync, tar, cp и т.п.
Итак, каким инструментом запускать бэкап?
- pg_dump — подходит для случаев, когда нужно сделать резервную копию таблицы, базы, схемы или данных.
- pg_basebackup — подходит для случаев, когда нужно сделать резервную копию целиком всего кластера БД или настроить hot standby реплику.
- rsync/tar/cp — также используются для случаев копирования всего кластера.
Когда только случился релиз PostgreSQL 9.0, резервное копирование выполнялось с помощью rsync.
Однако уже в 9.1 появился pg_basebackup, который обладает некоторыми преимуществами перед rsync:
* pg_basebackup не требует ssh доступа, но требует доступа к базе указанного в pg_hba.conf;
* pg_basebackup богаче по функциональности (копирование WAL, создание recovery.conf, встроенное сжатие gzip и пр.);
* pg_basebackup не требует отдельного вызова функций pg_start_backup/pg_stop_backup как это требуется при использовании rsync/tar/cp;
* pg_basebackup выполняет копирование быстрее чем rsync за счет использования протокола потоковой репликации.
Но есть и некоторые недостатки: * pg_basebackup идет out-of-the-box, и соответственно требует установленного postgres; * pg_basebackup не имеет встроенных функций для ограничения скорости копирования (обещают только в 9.4); * pg_basebackup требует включенных опций wal_level = hot_standby, max_wal_senders в postgresql.conf.
Здесь я буду рассматривать pg_basebackup, хотя и pg_dump тоже может использоваться в нижеперечисленных способах.
- Простое и без изысков резервное копирование с backup сервера в каталог /backup (каталог должен быть предварительно создан):
backup@backup ~ $ pg_basebackup -x -h db01.example.com -U backup -D /backup
- Копирование с пониженным приоритетом IO операций с помощью ionice, для случаев когда нужно уменьшить нагрузку на дисковый ввод-вывод от резервного копирования:
postgres@db01 ~ $ ionice -c 3 pg_basebackup -x -h db01.example.com -U backup -D /backup
- Копирование со сжатием в bzip2, для случаев, когда нужно использовать нестандартный для pg_basebackup алгоритм сжатия (gzip). Здесь мы передаем данные через стандартный вывод (stdout) на стандартный ввод (stdin) программе bzip2.
backup@backup ~ $ pg_basebackup -x --format=tar -h db01.example.com -U backup -D - |bzip2 -9 > /backup/db01/backup-$(date +%Y-%m-%d).tar.bz2
- Копирование со сжатием в несколько потоков (используем lbzip2 и задействуем 6 ядер). При таком раскладе можно задействовать простаивающие ядра и ускорить процесс сжатия.
backup@backup ~ $ pg_basebackup -x --format=tar -h db01.example.com -U backup -D - |lbzip2 -n 6 -9 > /backup/db01/backup-$(date +%Y-%m-%d).tar.bz2
- Здесь копирование запускается на сервере БД. Формируемая резервная копия отправляется на удаленный сервер по ssh.
postgres@db01 ~ $ pg_basebackup -x --format=tar -h 127.0.0.1 -U backup -D - |ssh backup@backup.example.com "tar xf - -C /backup/"
- Здесь копирование также запускается на сервере БД и выполняется отправка на удаленный сервер, но уже с архивированием в 6 потоков с помощью lbzip2.
backup@backup ~ $ pg_basebackup -x --format=tar -h 127.0.0.1 -U backup -D - |ssh backup@backup.example.com "lbzip2 -n 6 -9 > /backup/db01/backup-$(date +%Y-%m-%d).tar.bz2"
- Копирование на удаленный сервер с ограничением пропускной полосы до 10Мб с помощью pv и последующее архивирование на удаленной стороне. Этот вариант для случаев когда нужно передать не нагружая сеть.
backup@backup ~ $ pg_basebackup -x --format=tar -h 127.0.0.1 -U backup -D - |pv -r -b -L 10M |ssh backup@backup.example.com "bzip2 -9 > /backup/db01/backup-$(date +%Y-%m-%d).tar.bz2"
Тут стоит отметить что c 9.4 в pg_basebackup уже есть возможность ограничения скорости передачи (-r, —max-rate).
8. Копирование запускается на backup сервере, а далее происходит раздваивание потока на две части. Один поток сжимается с bzip2 (сам бэкап) и второй поток через tar копируется во временный каталог для последующей валидации. Способ редкоиспользуемый, но тут интересна сама реализация.
backup@backup ~ $ pg_basebackup -x --format=tar -h db01.example.com -U backup -D - |tee >(bzip2 -9 -c > /backup/db01/backup-$(date +%d-%b-%Y).tar.bz2) |tar xf - -C /backup/validation/
- Копирование с задействование lbzip2 на обоих узлах, для случаев, когда у сети маленькая пропускная способность. Сначала поток сжимается, затем передается по сети и затем расжимается на удаленной стороне. Здесь используется tar и требуется выполнение pg_start_backup(‘label_name’) на стороне postgres.
postgres@master # cd /var/lib/pgsql/9.3/data
postgres@master # tar cfO - ./ |lbzip2 -n 2 -5 |ssh postgres@standby "lbunzip2 -c -n 2 |tar xf - -C /var/lib/pgsql/9.3/data"
- Бэкапирование с шифрованием через GPG, для случаев, когда нужно зашифровать резервную копию. Предварительно следует создать ключи через gpg —gen-key (в моем случае ключи созданы с именем backup)
backup@backup ~ $ pg_basebackup -x --format=tar -h db01.example.com -U backup -D - |gpg -r backup -e |bzip2 -9 > /backup/db01/backup-$(date +%d-%b-%Y).tar.bz2
Для расшифровки резервной копии следует выполнить такую команду:
backup@backup ~ $ bzcat /backup/backup-09-May-2014.tar.bz2 |gpg -r backup -d |tar xf - -C /example/dir/
На этом всё, подведем итоги по инструментам:
- pg_basebackup — утилита для создания резервных копий postgres;
- lbzip2 — bzip2 сжатие с использованием нескольких ядер — если нужно запаковать быстрее (аналоги: pbzip2, pigz);
- ionice — регулировка класса и приоритета для планировщика ввода-вывода (также можно использовать nice для регулировки приоритета процессов для CPU планировщика);
- pv — контролируем объем передаваемых данных через pipe и т.о. используем для ограничения объема передаваемых данных в единицу времени (аналог — throttle);
- tar — утилита архивирования, нужна для вспомогательных целей, когда не используется сжатие bzip2/gzip;
- tee — чтение с stdin c записью в stdout и другие файлы (является частью coreutils);
- gpg — решает задачи по шифрованию.