Введение
В данной статье рассказано о базовых основах и принципах работы GTID с последующей практической настройкой репликации различными способами.
Репликация
По умолчанию в MySQL используется логический тип репликации Row-based с версии MySQL 5.7.7, ранее был Statement-Based Replication (SBR). Row-based является рекомендуемым типом для GTID.
Принцип работы GTID
GTID появился с MySQL 5.6 и представляет собой уникальный 128-битный глобальный идентификационный номер (SERVER_UUID), который увеличивается с каждой новой транзакцией. Выглядит GTID примерно так:
8182213e-7c1e-11e2-a6e2-080027635ef5
Классическая репликация MySQL без GTID использует позицию в бинарном логе. Но благодаря GTID больше не нужно разбираться с вычислениями позиции бинлога. Из преимуществ GTID является согласованность данных, т.е. на сервере (как на мастере, так и на слейве) будет подтверждена одна и только одна транзакция с одним GTID, а любые другие транзакции, имеющие такой же UUID, будут проигнорированы. Подробную теорию можно дополнительно изучить на официальном сайте MySQL.
Использование GTID – это хорошая практика, т.к. данные между мастером и слейвом более консистентные с GTID, настройка ещё быстрее и проще.
В MySQL при использовании GTID есть две глобальные переменные, о которых необходимо знать:
- gtid_executed – содержит набор всех транзакций из бинарного лога;
- gtid_purged – содержит набор транзакций, которые были зафиксированы на сервере, но не содержащиеся в бинарном логе. gtid_purged является подмножеством gtid_executed.
Вышеописанные переменные получают свои значения при каждом запуске MySQL. На мастер-сервере это выглядит так:
master > show global variables like 'gtid_executed';
+---------------+-------------------------------------------+
| Variable_name | Value |
+---------------+-------------------------------------------+
| gtid_executed | 9a511b7b-7059-11e2-9a24-08002762b8af:1-13 |
+---------------+-------------------------------------------+
master > show global variables like 'gtid_purged';
+---------------+------------------------------------------+
| Variable_name | Value |
+---------------+------------------------------------------+
| gtid_purged | 9a511b7b-7059-11e2-9a24-08002762b8af:1-2 |
+---------------+------------------------------------------+
Конфигурационные файлы
Для настройки репликации с использованием GTID в MYSQL в конфиге мастера достаточно прописать следующие значение:
gtid_mode=ON
log_bin=mysql-bin
log-slave-updates = 0
enforce-gtid-consistency
server_id=1
replicate-do-db = mybase
sync_binlog = 0
Ниже описание используемых обязательных директив из конфига:
- gtid_mode=ON – собственно, включает GTID;
- log_bin=mysql-bin – ведение бинарного лога для мастера (с него читает слейв). Когда на сервере используются GTID, и если бинарный лог не включен, при перезапуске сервера после аварийного выключения, некоторые GTID могут быть потеряны, что приведет к сбою репликации. При обычном завершении работы набор идентификаторов GTID из бинарного лога сохраняется в таблице mysql.gtid_executed;
- enforce-gtid-consistency – обязательный параметр для GTID, который не даёт всё поломать;
- server_id=1 идентификатор мастер сервера, цифровое значение может быть отличным от единицы в данном примере;
Также присутствуют необязательные директивы, но пару слов можно сказать и про них:
- log-slave-updates = 0 – необходим при использовании схемы А -> Б -> C, где А – гл. сервер для Б, а Б – гл. сервер для С, т.е. “гирляндная” или последовательная схема. Для случаев, когда данные от мастера пишутся в отдельный бинлог реплики для использования реплики в качестве мастера для другой реплики. Редкий случай;
sync_binlog = 0 – используется для синхронизации всех транзакций с двоичным файлом. По факту повышает надёжность транзакций для слейва при отказе ОС в случае сбоя. А также сильно влияет на производительность I\O хранилища, поэтому можно либо его отключить и положиться на надёжность отказоустойчивости системы, или же включить при наличии скоростного хранилища. В общем, использовать или нет – зависит от требований. Например, при установке sync_binlog=1 для БД Битрикс24, попугаи в тестах производительности на чтение\запись в БД могут заметно уменьшиться.
На слейве использование log_bin=mysql-bin вовсе не обязательно, т.к. идентификаторы GTID бинлога хранятся в таблице mysql.gtid_executed мастера – слейв будет читать их оттуда.
- Для слейв-сервера конфигурационный файл выглядит так:
server-id=2
gtid_mode=ON
enforce-gtid-consistency
Настройка репликации с mysqldump
При создании дампа БД мастер-сервера с использованием mysqldump, необходимые значения GTID для слейва уже будут содержаться в дампе. Это параметр gtid_purged, который является gtid_executed с мастера. После восстановления дампа на слейве, переменная gtid_executed будет равна gtid_purged.
При запуске репликации слейв отправит мастеру диапазон GTID, которые он выполнил у себя, а мастер отправит в ответ все отсутствующие транзакции, которых нет на слейве. Таким образом можно настраивать репликацию на работающей базе (снимать копию), не останавливая запись с помощью переменной read_only=1, но очень не желательно!
При необходимости снять дамп с работающей базы, нужно использовать ключ –single-transaction, который позволяет не блокировать таблицы на момент создания дампа, но при выполнении операторов вида ALTER TABLE, DROP и т.п., которые выполняют изменения, данные в дампе могут оказаться поврежденными.
Как правило, на небольших базах допустимо использовать –single-transaction при снятии дампа. А вот на более объемных, где часто совершается запись или изменения, рекомендуется сначала выполнить блокировку таблиц на запись с помощью set global read_only=1, а потом уже выполнять снятие дампа. Но такой вариант будет очень долгий, поэтому в следующем разделе будет рассказано про Percona XtraBackup.
- После получения дампа через mysqldump внутри него должно быть следующее:
grep -i purged dump.sql
SET @@GLOBAL.GTID_PURGED='9a511b7b-7059-11e2-9a24-08002762b8af:1-13'; # значение gtid_executed с мастера
У mysqldump есть важный параметр –set-gtid-purged, который позволяет управлять информацией глобальных идентификаторов транзакций (GTID), записанной в файл дампа, указывая, добавлять ли оператор SET @@ global.gtid_purged в вывод дампа. По умолчанию, значение этого флага auto, т.е. если GTID включен, то gtid_purged копируется, и наоборот.
При создании дампа для его последующей распаковки на реплике лучше всегда указывать явно флаг –set-gtid-purged=ON
Итого, чтобы правильно снять дамп через mysqldump с работающего мастера для настройки реплики необходимо:
- Перевести базу в read only – самый правильный вариант;
- Выполнить команду
mysqldump --single-transaction --set-gtid-purged=ON db_name > db_name.sql
- После чего необходимо создать пользователя на мастере для выполнения репликация (лучше всего отдельного). С данным пользователем слейв будет подключаться к мастеру:
master> GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'slave_ip' IDENTIFIED BY 'Strong_pass!';
- Важный момент! Необходимо убедиться, что слейв чистый, т.е. очищен от всех GTID. Для этого нужно на слейве выполнить следующее:
slave> reset master;
Согласно документации, reset slave при использовании GTID не меняет значение gtid_executed или gtid_purged, поэтому команда
reset master
на слейве – это не ошибка, а необходимость, чтобы убедиться, что слейв чистый и готов к настройке реплики.
И запускать репликацию со слейва привычным способом, как и ранее с позицией бинлога, но позиция указывается автоматически:
slave> CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_PORT=3306,
MASTER_USER='slave_user',
MASTER_PASSWORD='Strong_pass!',
MASTER_AUTO_POSITION=1;
slave> start slave;
slave> show slave status\G
Настройка репликации с Percona XtraBackup
При малых объемах БД и необходимости настройки реплики, легко и просто использовать mysqldump. Но когда объем БД за 10 Гб и более, то распаковка дампа может занять уже продолжительное время. Поэтому логичнее использовать инструмент XtraBackup от Percona. Он позволяет снимать копию с базы данных в момент её работы, используя возможности движка InnoDB.
Все транзакции, осуществленные в момент снятия копии, скапливаются в отдельном логе, который XtraBackup читает по ходу дела. После завершения бэкапа, XtraBackup применяет накопленные транзакции на снятую копию. Процесс выходит очень быстрым и позволяет переносить большие объемы данных.
Этот же инструмент можно использовать и при настройке репликации Master-Slave с GTID. XtraBackup поддерживает GTID с версии 2.1.0. Для работы с MySQL 5.7 необходима версия 2.4.
Процесс подготовки мастера и слейва ничем не отличается от ранее описанного при использовании XtraBackup. Необходимо также подготовить конфиг, указав использование GTID и ID сервера, а также создать пользователя для репликации, чтобы была возможность подключения со слейва.
На слейве параметр
innodb_log_file_size
должен быть того же размера, что и на мастере!
При работе с XtraBackup, все значения для подключения к MySQL берутся из конфигов.
- Для снятия полной копии всей БД и размещения её по пути
/mnt/share
необходимо выполнить следующую команду:
xtrabackup --backup --target-dir=/mnt/share
Пофайловая копия будет создана достаточно быстро. Скорость зависит от хранилища. Например, база объемом 60 Гб скопировалась за меньше, чем за 10 минут.
- Теперь необходимо выполнить подготовку бэкапа из /mnt/share, чтобы применились транзакции, выполненные в процессе снятия копии:
xtrabackup --prepare --target-dir=/mnt/share
- Подготовленную копию теперь необходимо восстановить на слейве. Для этого демон mysql слейва должен быть остановлен, а директория data_dir быть пуста:
systemctl stop mysqld
mv $MYSQL_DATA/data $MYSQL_DATA/data.old
mkdir $MYSQL_DATA/data
Переместить копию с мастера на слейв можно любым удобным способом.
Для более быстрого переноса снятой копии с мастера на слейв, можно настроить NFS-шару на мастере. Далее там же снять копию по пути шары, выполнить подготовку, а уже на слейве выполнять восстановление. Таким образом не нужно будет лишний раз гонять файлы через rsync.
- Выполнить восстановление копии мастера, находящейся по пути
/mnt/u01/share
, в целевую директорию data_dir, значение которой будет взято из конфига:
xtrabackup --copy-back --target-dir=/mnt/u01/share
Под капотом команды выше происходит полное копирование всех файлов из data_dir мастера в data_dir слейва. Необходимо обратить внимание, что все файлы ib* должны быть одного размера, как на мастере, так и на слейве, а также присутствовать в принципе в каталоге data_dir слейва. В противном случае может возникнуть ошибка “Table NAME doesn’t exist“, хотя по факту таблица будет существовать.
- Так как каталог под данные MySQL создавался руками, необходимо выдать корректные права и запустить БД:
chown -R mysql:mysql /mnt/u01/mysql
systemctl start mysqld
- До текущего момента процесс подготовки копии был стандартный. Копия снята, слейв запущен. Но теперь необходимо выполнить подготовку GTID для последующей настройки репликации. При снятии копии, на мастере создался файл xtrabackup_binlog_info, в котором указано значение GTID последней транзакции в данной копии. Это значение необходимо импортировать на слейв. Вывод будет следующий:
cat xtrabackup_binlog_info
mysql-bin.000027 191 8fd64058-edd8-11ea-a090-0242ac120002:1-26703081
На слейве установить значение GTID из файла xtrabackup_binlog_info для переменной GTID_PURGED:
SET GLOBAL GTID_PURGED="8fd64058-edd8-11ea-a090-0242ac120002:1-26703081";
- И далее выполнить стандартную настройку репликации, подключаясь к мастеру с использованием GTID:
CHANGE MASTER TO
-> MASTER_HOST='MASTER_IP',
-> MASTER_PORT=3306,
-> MASTER_USER='slave_user',
-> MASTER_PASSWORD='Strong_pass!',
-> MASTER_AUTO_POSITION = 1;
START SLAVE;
В данном случае по сути было выполнено тоже самое, что и через mysqldump, но с помощью XtraBackup. А значение GTID_PURGED, которое хранится обычно в дампе, было создано вручную – это единственный нюанс, который нужно учесть.
Заключение
В статье были рассмотрены теоретические сведения о работе GTID и настройке репликации различными способами. Резюмируя, ещё раз подчеркну, что для малых БД подойдет mysqldump, а для более больших проектов уже XtraBackup. Каждый инструмент удобен по-своему и можно применять в зависимости от ситуации.
А откуда информация, что “innodb_log_file_size должен быть того же размера, что и на мастере” ? Не нашел такого ни в одной доке… А если у меня слейв и мастер в разы отличаются объемом памяти ?
Да, вы правы, такого требования в доке нет. Не помню, откуда я это взял, скорее всего делал просто по аналогии: и мастер и слейв, т.к. обычно в моём случае они полностью идентичны по ресурсам.
Спасибо за статью, очень удобно использовать как шпаргалку. Изложено довольно кратко, но вся важная инфа присутствует.
Рад, что кому-то это пригодилось
Хорошая статья, спасибо. Уловил наконец некоторые вещи, которые в официальной документации невнятно описаны.
Рад, что вам это помогло