UMGUM.COM 

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

1 февраля 2018  (обновлено 11 ноября 2018)

OS: "Linux Debian Wheezy/Jessie/Stretch", "Linux Ubuntu Xenial/Bionic LTS".
Application: MySQL/MariaDB, "Percona XtraBackup".

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

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

Решение проблемы есть - это свободно распространяемая утилита "Percona XtraBackup", создающая "бинарный дамп" данных СУБД, хранимых в формате InnoDB, работая по принципу, схожему с используемым утилитой "pg_basebackup", предназначенной для PostgreSQL. Так же вначале копируются файлы данных, как они есть, которые дополняются журналом транзакций скопившихся за время процедуры копирования (в разы более быстрой, по сравнению в SQL-дампом, кстати). При этом СУБД не перестаёт обслуживать клиентов - утилита "XtraBackup" не вмешивается в её работу, лишь считывая генерируемые таковой данные.

Мало того, что "бинарный дамп" создаётся быстрее и при этом не блокируется работа исходной СУБД, так он ещё и развёртывается моментально - ведь это копия файлов данных, которые можно подложить пустому инстансу "MySQL/MariaDB" и оно просто заработает (а гигабайтные SQL-дампы заливаются в БД порой часами)!


Обращаю внимание на то, что утилита "XtraBackup" предназначена для резервного копирования данных таблиц в формате InnoDB - в таком случае описанные выше выгоды максимальны. Её можно использовать и с форматом MyISAM, но в таком случае БД будет совсем ненадолго заблокирована к концу резервного копирования для сбора нарушающих консистентность SQL-запросов.

Установка "Percona XtraBackup".

В репозиториях стабильных релизов Linux-ов чаще всего недостаточно свежие версии нужной нам утилиты. Удобнее всего подключить репозиторий от разработчиков и загрузить программное обеспечение оттуда:

# vi /etc/apt/sources.list.d/percona.list

deb http://repo.percona.com/apt xenial main
deb-src http://repo.percona.com/apt xenial main

В конфигурации репозитория традиционно используются символическое имя дистрибутива, выяснить которое можно следующим образом, например:

$ lsb_release -c

Codename: xenial

# aptitude update
# aptitude install percona-xtrabackup-24

Какое-то время назад решение резервного копирования "xtrabackup" от "Percona" предназначалось только для баз данных MySQL формата InnoDB (ну и самолепных XtraDB, конечно). Чтобы удержаться на волне популярности разработчикам почти сразу после запуска продукта пришлось сделать Perl-обёртку "innobackupex", которая вдобавок могла оперировать и с таблицами формата MyISAM.

Однако сейчас, с версий выше "2.3", основная утилита "xtrabackup" уже умеет делать всё, а "innobackupex" является символической ссылкой на первую, для сохранения обратной совместимости с уже работающими схемами. Мало того, имя "innobackupex" объявлено устаревшим и от его использования следует отказаться.

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

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

Указываем выносить каждую таблицу в два физических файла - определения таблицы и данных:

# vi /etc/mysql/mysql.cnf

....
[mysqld]
....
innodb_file_per_table = 1
....

Применение параметра пофайлового разделения таблиц потребует перезагрузки СУБД:

# /etc/init.d/mysql restart

Иногда, если MySQL-сервер обслуживает большие базы данных с множеством таблиц InnoDB-формата, при попытке полного резервного копирования таковых может случится ошибка исчерпания лимита на количество одновременно открытых файлов, установленного в конфигурации MySQL и наследуемого утилитой резервного копирования "xtrabackup":

InnoDB: Error number 24 means 'Too many open files'

По умолчанию в MySQL установлено ограничение в 1024 одновременно открытых файлов:

mysql> show global variables like "open_files%";
+------------------+------+
| open_files_limit | 1024 |
+------------------+------+

Ради интереса можно точно узнать, насколько требуется увеличить лимит (пример с одной из моих инсталляций):

# find /var/lib/mysql/ -name "*.ibd" | wc -l

1189

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

# vi /etc/mysql/mysql.cnf

....
[xtrabackup]
open-files-limit=250000

Конечно, можно увеличить лимит вообще для всей СУБД, разместив корректирующий параметр в блоке переменных "[mysqld]".

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

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

# mkdir -p /var/backups/xtrabackup
# chown -R mysql:mysql /var/backups/xtrabackup

Простейшее полное "бинарное" резервное копирование всех баз данных "MySQL/MariaDB" инстанса делается одной командой (целевая директория для резервной копии должна быть пуста):

# xtrabackup --backup --target-dir=/var/backups/xtrabackup

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

# xtrabackup --prepare --target-dir=/var/backups/xtrabackup

....
xtrabackup version 2.4.12 based on MySQL server 5.7.19 Linux (x86_64) (revision id: 170eb8c)
....
InnoDB: Log scan progressed past the checkpoint lsn 5734741238643
InnoDB: Doing recovery: scanned up to log sequence number 5734746481152 (3%)
....
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Progress in percent: 0 1 2 3 4 5 6 7 ... 95 96 97 98 99
InnoDB: Apply batch completed
....
180718 15:46:43 completed OK!

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

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

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

# /etc/init.d/mysql stop
# mv /var/lib/mysql /var/lib/mysql.old
# rsync -avrP /var/backups/xtrabackup /var/lib/mysql
# chown -R mysql:mysql /var/lib/mysql
# /etc/init.d/mysql start

Немного об опциональном в "Percona XtraBackup".

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

# xtrabackup --backup --no-timestamp --defaults-file=/etc/mysql/mysql.cnf --user=root --password=`cat /root/.mysql` --throttle=40 --target-dir=/var/backups/xtrabackup 2>$1 > /var/log/xtrabackup.log

В "XtraBackup" встроено средство выдачи результирующих данных скомпонованных в виде потока tar-формата, от чего в самом простом случае мы получаем на выходе монолитный файл:

# xtrabackup --backup --stream=tar --target-dir=/var/backups/xtrabackup > /var/backups/xtrabackup/backup.tar

Выдаваемый "XtraBackup" поток можно отправлять через "pipe". Как минимум это позволит упаковать данные "на лету", сэкономив место для хранения таковых (базы данных MySQL хорошо сжимаются GZip, делаясь раз в пять меньше):

# xtrabackup --backup --stream=tar --target-dir=/var/backups/xtrabackup | gzip - > /var/backups/xtrabackup/backup.tar.gz

Развёртывание созданного в спарке "xtrabackup+tar" архива имеет свои особенности - в частности, необходимо использовать ключ "-i", предписывающий игнорировать "занулённые области", встречающиеся в файлах, созданных в процессе упаковки потока данных "на лету":

# tar -xizf backup.tar.gz


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


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