UMGUM.COM 

PostgreSQL + "basebackup" ( Резервное копирование БД "PostgreSQL" путём создания полного "бинарного дампа" данных СУБД. )

15 января 2018  (обновлено 18 ноября 2018)

OS: "Linux Debian 8/9", "Linux Ubuntu 14/16/18 LTS".
Application: "PostgreSQL v9.2/10", "pg_basebackup".

Задача: обеспечить возможность максимально быстрого снятия резервной копии всех данных действующей СУБД "PostgreSQL", без блокирования работы таковой даже на кратчайший момент времени.

Резервное копирование крупных и активно изменяемых баз данных путём выгрузки классического "текстового (логического) дампа", состоящего из набора SQL-команд наполнения таблиц практически неприменимо: это очень долго (SQL-дампы БД за десятки Гигабайт могут более получаса генерироваться), сильно нагружает дисковую и вычислительную подсистемы несущего сервера валом запросов на чтение и последующую запись, а также не всегда гарантирует консистентное состояние финального набора данных (в силу того, что во время длительного процесса создания последовательного набора SQL-строк после сохранения в резервной копии строки из начала набора таковая может быть изменена, и связанные с ней данные в конце набора будут ссылаться на уже устаревшие сведения).

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

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

Никаких утилит или приложений, помимо комплектных самой СУБД "PostgreSQL" для решения нашей задачи не требуется. Приступим.


Предварительная настройка СУБД.

Функционал снятия "бинарных" резервных копий в "PostgreSQL" реализован через подсистемы репликации и журналирования транзакций WAL (Write-Ahead Log). Активируем таковые и определяем ряд ключевых параметров:

# vi /etc/postgresql/9.5/main/postgresql.conf

....
# Активируем режим журналирования, достаточный для снятия "горячих" резервных копий
wal_level = archive

# Задаём количество хранящихся в директории "pg_xlog" файлов журнала WAL, ротируемых по мере появления свежих данных
# (в среднем один файл по 16MB, то есть в примере мы забираем места до полугигабайта)
wal_keep_segments = 32

# Явно ограничиваем число обслуживаемых соединений передачи данных в режиме "репликации"
# (один поток для выгрузки файлов данных и второй для текущих транзакций)
max_wal_senders = 2
....

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

Так как функционал выгрузки файлов "баз данных" и журналов транзакций в "PostgreSQL" реализован через подсистему репликации, а для получения доступа ко всему этому содержимому всё равно нужны весьма высокие полномочия доступа, то проще всего будет разрешить локально аутентифицированному пользователю "postgres" обращение к СУБД рамках специального режима исполнения функционала репликации, ограничив область подключений локальным "сокетом":

# vi /etc/postgresql/9.5/main/pg_hba.conf

....
# TYPE  DATABASE     USER      ADDRESS  METHOD
# --------------------------------------------
....

# Replication connections login by host trust
local   replication  postgres           peer

Изменение вышеприведённых параметров требует перезагрузки сервера СУБД:

# /etc/init.d/postgresql restart

Пример резервного копирования посредством "pg_basebackup".

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

# mkdir -p /var/backups/postgresql
# chown -R postgres:postgres /var/backups/postgresql
# chmod -R go-rwx /var/backups/postgresql

В комплекте программного обеспечения "PostgreSQL" имеется утилита "pg_basebackup", через механизм репликации вытаскивающая "бинарный (файловый) бэкап" и журнал транзакций. Данные между исходным каталогом СУБД и файловой структурой резервной копии синхронизируются в полном объёме, включая вообще всё внутри директории таковых (даже свежие журналы WAL, успевшие накопиться за время процедуры транспортировки), так что есть смысл предварительно зачистить место:

# rm -r /var/backups/postgresql/*

Запускаем процедуру снятия локальной полной "бинарной" резервной копии всех имеющихся на сервере "баз данных" PostgreSQL:

# sudo -u postgres pg_basebackup -v -X fetch -R -D /var/backups/postgresql

pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
transaction log start point: ...
transaction log end point: ...
pg_basebackup: base backup completed

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

Опция "-X fetch" указывает "pg_basebackup" осуществить загрузку в два этапа: вначале файлы "баз данных" как таковых, а потом добрать файлы журнала WAL, содержащие транзакции случившиеся после начала копирования файлов основного массива данных и приложить их к уже имеющимся журналам. Если выбрать метод загрузки данных "-X stream" (используемый по умолчанию, кстати), то файлы журналов WAL не будут загружаться, а случающиеся во время резервного копирования транзакции будут передаваться параллельным основному потоком и применяться к загруженным файлам данных "на лету". В целом второй способ удобнее, но он появился только в "PostgreSQL v9.2".

Как вариант, можно указать утилите упаковывать файлы в монолитный Tar-архив, сжимаемый на лету в формате GZip (но потом его придётся раскрывать, на что уходит время):

# sudo -u postgres pg_basebackup -X fetch -R -F tar -z -D /var/backups/postgresql

Пример восстановления данных из резервной копии.

Восстановление или запуск на новом месте из полной "бинарной" резервной копии, полученной в результате работы "pg_basebackup", элементарно - достаточно остановить целевой PostgreSQL-сервер и подменить содержимое его директории данных резервной копией:

# /etc/init.d/postgresql stop
# mv /var/lib/postgresql/9.5/main /var/lib/postgresql/9.5/main.old
# rsync -avrP /var/backups/postgresql /var/lib/postgresql/9.5/main
# chown -R postgres:postgres /var/lib/postgresql
# chmod -R go-rwx /var/lib/postgresql/
# /etc/init.d/postgresql start

Одно из требований "PostgreSQL" - наличие конфигурационного файла "recovery.conf" для перехода в режим восстановления "баз данных" путём применения транзакций из WAL-журнала - удовлетворяется утилитой "pg_basebackup" без особых на то указаний. Сразу после "проигрывания" всего WAL-журнала и восстановления целостности БД файл автоматически переименовывается в "recovery.conf.done", а сервер СУБД переходил в нормальный режим обслуживания клиентов.


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )