Глобальный идентификатор транзакции
Термины master и slave исторически использовались в репликации, но сейчас предпочтительнее термины primary и replica. Старые термины всё ещё используются в некоторых частях документации и в командах MariaDB, хотя MariaDB 10.5 начала процесс переименования. Процесс документации продолжается. Следите за прогрессом на MDEV-18777.
Обратите внимание, что MariaDB и MySQL имеют разные реализации GTID, и они несовместимы друг с другом. MariaDB может быть slave для MySQL master, но MySQL не может быть slave для MariaDB master.
Обзор
Репликация MariaDB в целом работает следующим образом (см. Обзор репликации для получения дополнительной информации):
На сервере-мастере все обновления базы данных (DML и DDL) записываются в бинарный журнал в качестве событий binlog. Сервер-реплика подключается к первичному серверу и считывает события binlog, а затем применяет события локально, чтобы воспроизвести те же изменения, что и на первичном сервере. Сервер может быть одновременно первичным и репликой, и поэтому события binlog могут быть реплицированы через несколько уровней серверов.
Сервер-реплика отслеживает позицию в бинарном журнале первичного сервера последнего обработанного события на реплике. Это позволяет серверу-реплике повторно подключиться и возобновить работу с того места, где он остановился после временной остановки репликации. Это также позволяет реплике отключиться, быть клонированной, а затем новой реплике возобновить репликацию с того же первичного сервера.
Глобальный идентификатор транзакции (GTID) добавляет новое событие, связанное с каждой группой событий в бинарном журнале. (Группа событий — это набор событий, которые всегда применяются как единое целое. Их лучше всего понимать как «транзакцию», хотя они также включают не транзакционные DML-запросы, а также DDL). Когда группа событий реплицируется с первичного сервера на сервер-реплику, глобальный идентификатор транзакции сохраняется. Поскольку ID является глобально уникальным для всей группы серверов, это упрощает уникальную идентификацию тех же событий binlog на разных серверах, которые реплицируют друг друга (это не было легко осуществимо до MariaDB 10.0.2).
Преимущества
Использование глобального идентификатора транзакции предоставляет два основных преимущества:
1. Легко изменить сервер-реплику, чтобы он подключался и реплицировал данные с другого первичного сервера.
Реплика запоминает глобальный идентификатор транзакции последней группы событий, применённой с предыдущего первичного сервера. Это упрощает определение точки возобновления репликации на новом первичном сервере, поскольку глобальные идентификаторы транзакций известны во всей иерархии репликации. Это не так в случае репликации старого стиля; в этом случае реплика знает только имя файла и смещение последнего обработанного события на старом первичном сервере. Нет простого способа определить из этого правильное имя файла и смещение на новом первичном сервере.
2. Состояние реплики записывается безопасным способом при сбоях.
Реплика отслеживает свою текущую позицию (глобальный идентификатор транзакции последней применённой транзакции) в системной таблице mysql.gtid_slave_pos. Если эта таблица использует транзакционный движок хранения (например, InnoDB, который является по умолчанию), то обновления состояния выполняются в той же транзакции, что и обновления данных. Это делает состояние безопасным при сбоях; если сервер-реплика выходит из строя, восстановление после сбоя при перезапуске гарантирует, что зарегистрированная позиция репликации соответствует изменениям, которые фактически были реплицированы. Это не так для репликации старого стиля, где состояние записывается в файл relay-log.info, который обновляется независимо от фактических изменений данных и может легко разойтись, если сервер-реплика выйдет из строя. (Это работает для DML транзакционных таблиц; не транзакционные таблицы и DDL в целом не безопасны при сбоях в MariaDB.)
Из-за этих двух преимуществ рекомендуется использовать глобальный идентификатор транзакции для любых установок репликации на основе MariaDB 10.0.2 или более поздней версии. Однако репликация старого стиля продолжает работать как обычно, поэтому нет необходимости изменять существующие настройки. Глобальный идентификатор транзакции плавно интегрируется со старой репликацией, и их можно свободно использовать вместе в одной иерархии репликации. Для использования глобального идентификатора транзакции не требуется специальной настройки сервера. Однако он должен быть явно задан для сервера-реплики с соответствующим параметром CHANGE MASTER; по умолчанию сервер-реплика использует репликацию старого стиля для обеспечения обратной совместимости.
Реализация
Глобальный идентификатор транзакции, или GTID, состоит из трёх чисел, разделённых дефисами '-'. Например:
0-1-10
- Первое число 0 — это идентификатор домена, специфичный для глобального идентификатора транзакции (подробнее об этом ниже). Это 32-битовое беззнаковое целое число.
- Второе число — идентификатор сервера, такой же, как используется и в репликации старого стиля. Это 32-битовое беззнаковое целое число.
- Третье число — порядковый номер. Это 64-битовое беззнаковое целое число, монотонно увеличивающееся для каждой новой группы событий, залогированных в бинарный журнал.
Идентификатор сервера настраивается на идентификатор сервера, на котором группа событий впервые залогирована в бинарный журнал. Порядковый номер увеличивается на сервере для каждой залогированной группы событий. Поскольку идентификаторы серверов должны быть уникальными для каждого сервера, эта пара (id_сервера, порядковый_номер) и весь GTID являются глобально уникальными.
Использование 64-битового числа обеспечивает достаточный диапазон, чтобы в обозримом будущем не возникло риска переполнения. Тем не менее, не следует искусственно (устанавливая gtid_seq_no) вводить GTID с очень большим порядковым номером, близким к пределу 64-бита.
Идентификатор домена
Когда события реплицируются с первичного сервера на сервер-реплику, события всегда записываются в бинарный журнал реплики в том же порядке, в котором они были считаны из бинарного журнала первичного сервера. Таким образом, если когда-либо существует только один первичный сервер, получающий (не репликационные) обновления за раз, то порядок binlog будет идентичен на каждом сервере в иерархии репликации.
Этот согласованный порядок binlog используется репликой для отслеживания её текущей позиции в репликации. В основном, реплика запоминает GTID последней группы событий, реплицированной с первичного сервера. При повторном подключении к первичному серверу, будь то тот же или новый, она отправляет эту позицию GTID первичному серверу, и первичный сервер начинает отправлять события с первого события после соответствующей группы событий.
Однако, если пользовательские обновления выполняются независимо на нескольких серверах одновременно, то, как правило, невозможно обеспечить идентичный порядок binlog на всех серверах. Это может произойти при использовании многоисточниковой репликации, с топологиями с множественными первичными серверами или просто при выполнении ручных обновлений на реплике, которая реплицирует данные с активного первичного сервера. Если порядок binlog на новом первичном сервере отличается от порядка на старом первичном сервере, то реплике недостаточно отслеживать один GTID для полного отображения текущего состояния.
Идентификатор домена, первая компонента GTID, используется для обработки этого.
В общем случае, binlog не представляет собой единый упорядоченный поток. Скорее, он состоит из ряда различных потоков, каждый из которых идентифицируется своим собственным идентификатором домена. Внутри каждого потока GTID всегда имеют одинаковый порядок в каждом бинарном журнале серверов. Однако различные потоки могут чередоваться по-разному на разных серверах.
Затем сервер-реплика отслеживает свою позицию репликации, записывая последний применённый GTID в каждом потоке репликации. При подключении к новому первичному серверу реплика может начать репликацию с другой точки в бинарном журнале для каждого идентификатора домена.
Для получения более подробной информации об использовании установок с несколькими первичными серверами и нескольких идентификаторах доменов см. Использование с многоисточниковой репликацией и другими многопервичными настройками.
В простых установках репликации всегда используется только один первичный сервер, обновляемый приложением в любой момент времени. В таких установках требуется только один поток репликации. Тогда идентификатор домена можно игнорировать и оставить по умолчанию 0 на всех серверах.
Использование глобальных идентификаторов транзакций
Глобальный идентификатор транзакции включён автоматически. Каждая группа событий, залогированных в бинарный журнал, получает событие GTID, как можно увидеть с помощью mariadb-binlog или SHOW BINLOG EVENTS.
Реплика автоматически отслеживает GTID последней применённой группы событий, как можно увидеть из переменной gtid_slave_pos:
SELECT @@GLOBAL.gtid_slave_pos 0-1-1
При подключении реплики к первичному серверу она может использовать либо глобальный идентификатор транзакции, либо имя файла/смещение старого стиля, чтобы определить, с какой позиции в бинарных журналах первичного сервера начать репликацию. Для использования глобального идентификатора транзакции используйте опцию CHANGE MASTER master_use_gtid:
CHANGE MASTER TO master_use_gtid = { slave_pos | current_pos | no }
Реплика настраивается на использование GTID CHANGE MASTER TO master_use_gtid=slave_pos. Когда реплика подключается к первичному серверу, она начнёт репликацию с позиции последнего реплицированного GTID на реплике, что можно увидеть в переменной gtid_slave_pos. Поскольку GTID одинаковы на всех серверах репликации, реплику затем можно направить на другой первичный сервер, и правильная позиция будет определена автоматически.
Но предположим, что мы настраиваем два сервера A и B, где A — первичный, а B — реплика. Он работает некоторое время. Затем в какой-то момент мы останавливаем A, и B становится новым первичным сервером. Позже мы хотим добавить A обратно, на этот раз в качестве реплики.
Поскольку A никогда не был репликой раньше, у него нет предыдущих реплицированных GTID, и gtid_slave_pos будет пустым. Чтобы разрешить автоматическое добавление A в качестве реплики, можно использовать master_use_gtid=current_pos. Это позволит подключиться, используя значение переменной gtid_current_pos вместо gtid_slave_pos, что также учитывает GTID, записанные в binlog, когда сервер был первичным.
При использовании master_use_gtid=current_pos нет необходимости учитывать, был ли сервер первичным или репликой до использования CHANGE MASTER. Но необходимо следить за тем, чтобы не вносить дополнительные транзакции в бинарный журнал сервера-реплики, которые не предназначены для репликации на другие серверы. Если такая дополнительная транзакция является последней при запуске реплики, она будет использоваться в качестве начальной точки репликации. Вероятно, это приведёт к ошибке, потому что эта транзакция отсутствует на первичном сервере. Чтобы избежать попадания локальных изменений на сервере-реплике в binlog, установите sql_log_bin в 0.
Если нежелательно, чтобы изменения в binlog на реплике влияли на позицию репликации GTID, то следует использовать master_use_gtid=slave_pos. Тогда реплика всегда будет подключаться к первичному серверу в позиции последнего реплицированного GTID. Это может избежать некоторых неожиданностей для пользователей, которые ожидают поведения, согласующегося с традиционной репликацией, где позиция репликации никогда не изменяется локальными изменениями, выполненными на сервере.
Когда режим GTID strict включен (путем установки @@GLOBAL.gtid_strict_mode в 1), обычно лучше использовать current_pos. В строгом режиме дополнительные транзакции на первичном сервере запрещены.
Если реплика настроена с отключенным binlog, current_pos и slave_pos эквивалентны.
Даже когда реплика настроена на подключение со старым форматом имени файла binlog и смещения (CHANGE MASTER TO master_log_file=..., master_log_pos=...), она по-прежнему будет отслеживать текущую позицию GTID в @@GLOBAL.gtid_slave_pos. Это означает, что существующую реплику, ранее настроенную и работающую, можно изменить на подключение с GTID (к тому же или новому мастеру) просто с помощью:
CHANGE MASTER TO master_use_gtid = slave_pos
Реплика запоминает, что master_use_gtid=slave_pos|master_pos было указано, и будет использовать его также для последующих подключений, пока явно не будет изменено указанием master_log_file/pos=... или master_use_gtid=no. Текущее значение можно увидеть как поле Using_Gtid в запросе SHOW SLAVE STATUS:
SHOW SLAVE STATUS\G ... Using_Gtid: Slave_pos
Сервер репликации внутренне использует таблицу mysql.gtid_slave_pos для хранения позиции GTID (и таким образом сохраняет значение @@GLOBAL.gtid_slave_pos после перезагрузки сервера). После обновления сервера до версии 10.0 необходимо запустить mysql_upgrade (как обычно), чтобы создать таблицу.
Для обеспечения отказоустойчивости эта таблица должна использовать транзакционный движок хранения, такой как InnoDB. Когда MariaDB впервые установлен (или обновлен до 10.0.2+), таблица создается с использованием движка хранения по умолчанию - который сам по умолчанию является InnoDB. Если необходимо изменить движок хранения для этой таблицы (например, чтобы сделать ее транзакционной на системе, настроенной с MyISAM в качестве движка хранения по умолчанию), используйте ALTER TABLE:
ALTER TABLE mysql.gtid_slave_pos ENGINE = InnoDB
Таблица mysql.gtid_slave_pos не должна изменяться каким-либо иным способом. В частности, не пытайтесь обновлять строки в таблице, чтобы изменить представление реплики о текущей позиции GTID; вместо этого используйте
SET GLOBAL gtid_slave_pos = '0-1-1'
Начиная с MariaDB 10.3.1, переменная сервера gtid_pos_auto_engines предпочтительно устанавливается для автоматического управления сервером. Подробности см. в описании таблицы mysql.gtid_slave_pos.
Использование current_pos против slave_pos
При установке параметра репликации MASTER_USE_GTID у вас есть возможность включить Global Transaction IDs, используя либо значение current_pos, либо slave_pos.
Использование значения current_pos заставляет реплику устанавливать свою позицию на основе системной переменной gtid_current_pos, которая является объединением gtid_binlog_pos и gtid_slave_pos. Использование значения slave_pos заставляет реплику вместо этого устанавливать свою позицию на основе системной переменной gtid_slave_pos.
Вы можете столкнуться с проблемами при использовании значения current_pos, если вы выполняете локальные транзакции на реплике. Например, если вы выполняете оператор INSERT или каким-либо образом записываете в таблицу, в то время как потоки репликации реплики остановлены, то новые локальные GTIDs могут быть сгенерированы в gtid_binlog_pos, что повлияет на значение реплики gtid_current_pos. Это может вызвать ошибки при перезапуске потоков репликации, так как локальные GTIDs отсутствуют на первичном сервере.
Вы можете исправить эту проблему, установив параметр репликации MASTER_USE_GTID в значение slave_pos вместо current_pos. Например:
CHANGE MASTER TO MASTER_USE_GTID = slave_pos; START SLAVE;
Использование GTID с параллельной репликацией
Если используется параллельная репликация, события, которые были записаны с GTID с разными значениями gtid_domain_id, могут быть применены параллельно в неупорядоченном порядке.
Использование GTID с MariaDB Galera Cluster
Начиная с MariaDB 10.1.4, MariaDB Galera Cluster имеет ограниченную поддержку GTID. Подробнее см. Использование MariaDB GTID с MariaDB Galera Cluster.
Настройка нового сервера реплики с помощью Global Transaction ID
Настройка нового сервера реплики с помощью идентификатора глобальной транзакции мало чем отличается от настройки старого стиля реплики. Основные шаги:
1. Настройте новый сервер и загрузите его начальными данными.
2. Запустите репликацию реплики с соответствующей точки в binlog первичного сервера.
Настройка новой реплики с пустым сервером
Самый простой способ для целей тестирования, вероятно, состоит в настройке нового пустого сервера реплики и репликации всех бинарных журналов первичного сервера с самого начала (это обычно нецелесообразно в реальной производственной настройке, так как начальные файлы бинарных журналов, вероятно, будут удалены или их применение займет слишком много времени).
Сервер реплики устанавливается обычным способом. По умолчанию позиция GTID для вновь установленного сервера пустая, что заставляет реплику реплицировать с начала бинарных журналов первичного сервера. Но если реплика использовалась для других целей ранее, начальную позицию можно явным образом установить в пустую сначала:
SET GLOBAL gtid_slave_pos = "";
Далее, укажите реплику на мастер с помощью CHANGE MASTER. Укажите master_host и т. д. как обычно. Но вместо ручного указания master_log_file и master_log_pos используйте master_use_gtid=current_pos (или slave_pos для автоматического выполнения GTID):
CHANGE MASTER TO master_host="127.0.0.1", master_port=3310, master_user="root", master_use_gtid=current_pos; START SLAVE;
Настройка новой реплики из резервной копии
Обычный способ настройки новой реплики - создание резервной копии с существующего сервера (первичного или реплики в топологии репликации), а затем восстановление этой резервной копии на сервере, выступающем в роли новой реплики, и настройка ее для начала репликации с соответствующей точки в бинарном журнале первичного сервера.
Важно, чтобы позиция, с которой начинается репликация, точно соответствовала состоянию данных в момент создания резервной копии. В противном случае реплика может получить данные, отличающиеся от первичного сервера из-за отсутствия или дублирования транзакций. Конечно, если во время процесса создания резервной копии на сервере, с которого делается резервная копия, нет записей, то просто SHOW MASTER STATUS даст правильную позицию.
Обратитесь к описанию конкретного инструмента резервного копирования, чтобы определить, как получить позицию бинарного журнала, соответствующую резервной копии.
После получения текущей позиции бинарного журнала для резервной копии в форме имени файла бинарного журнала и позиции, соответствующую позицию GTID можно получить из BINLOG_GTID_POS() на сервере, с которого была взята резервная копия:
SELECT BINLOG_GTID_POS("master-bin.000001", 600);
Новая реплика может начать репликацию с первичного сервера, установив правильное значение для gtid_slave_pos, а затем выполнив CHANGE MASTER со соответствующими значениями для первичного сервера, а затем запустив потоки репликации, выполнив START SLAVE. Например:
SET GLOBAL gtid_slave_pos = "0-1-2"; CHANGE MASTER TO master_host="127.0.0.1", master_port=3310, master_user="root", master_use_gtid=slave_pos; START SLAVE;
Этот метод особенно полезен при настройке новой реплики из резервной копии первичного сервера. Не забудьте убедиться, что значение server_id, настроенное на новой реплике, отличается от значения любого другого сервера в топологии репликации.
Если резервная копия была создана с существующего сервера реплики, то у новой реплики уже должна быть правильная позиция GTID, хранящаяся в таблице mysql.gtid_slave_pos. Это предполагает, что эта таблица была резервным образом скопирована и что это было сделано согласованно с изменениями других таблиц. В этом случае нет необходимости явно искать позицию GTID на старом сервере и устанавливать ее на новой реплике - она уже будет правильно загружена из таблицы mysql.gtid_slave_pos. Однако это не работает, если резервная копия была создана с первичного сервера - в этом случае текущая позиция GTID содержится в бинарном журнале, а не в таблице mysql.gtid_slave_pos или какой-либо другой таблице.
Настройка новой реплики с помощью Mariabackup
Новую реплику можно легко настроить с помощью Mariabackup, который является форком Percona XtraBackup. Подробнее см. Настройка реплики с помощью Mariabackup.
Настройка новой реплики с помощью mariadb-dump
Новую реплику также можно настроить с помощью mariadb-dump.
mariadb-dump автоматически включает позицию GTID в качестве комментария в файле резервной копии, если используется опция --master-data или --dump-slave. Также при использовании опции --gtid вместе с опциями --master-data или --dump-slave он автоматически включает команды для установки gtid_slave_pos и выполнения CHANGE MASTER в файле резервной копии.
Переключение существующей реплики старого стиля на использование GTID.
Если уже запущена реплика, использующая старое позиционирование файла/смещения бинарного лога, то это можно изменить на использование идентификатора GTID напрямую. Это может быть полезно, например, при обновлении, или в случаях, когда уже существуют инструменты для настройки новой реплики с использованием старых позиций бинарного лога.
Когда реплика подключается к первичной базе данных, используя старые позиции бинарного лога, и первичная база данных поддерживает GTID (т.е. это MariaDB 10.0.2 или более поздняя версия), то реплика автоматически загружает позицию GTID при подключении и обновляет её во время репликации. Таким образом, после того, как реплика хотя бы один раз подключилась к первичной базе данных, поддерживающей GTID, она может быть переключена на использование GTID без каких-либо дополнительных действий;
STOP SLAVE; CHANGE MASTER TO master_host="127.0.0.1", master_port=3310, master_user="root", master_use_gtid=current_pos; START SLAVE;
(В более поздней версии, вероятно, будет добавлена возможность настроить реплику таким образом, чтобы она подключалась с файлом/смещением бинарного лога старого стиля в первый раз и автоматически переключалась на использование GTID при последующих подключениях.)
Изменение реплики для репликации с другого первичного сервера
После того, как репликация запущена с использованием GTID (master_use_gtid=current_pos|slave_pos), реплику можно направить на новый первичный сервер, просто указав в команде CHANGE MASTER новый master_host (и, при необходимости, master_port, master_user и master_password):
STOP SLAVE; CHANGE MASTER TO master_host='127.0.0.1', master_port=3312; START SLAVE;
Реплика сохраняет запись GTID последней применённой транзакции со старого первичного сервера, и поскольку GTID идентичны на всех серверах в иерархии репликации, реплика просто продолжит с соответствующей точки в бинарном логе нового первичного сервера.
Важно понять, как работает изменение первичного сервера. Бинарный лог представляет собой упорядоченный поток событий (или несколько потоков, по одному на домен репликации (см. Использование с многоисточниковой репликацией и другими многопервичными схемами)). События внутри потока всегда применяются в том же порядке на каждой реплике, которая его реплицирует. MariaDB GTID полагается на этот порядок, поэтому достаточно запомнить только одну точку в потоке. Поскольку порядок событий одинаков на каждом сервере, переключение на точку с тем же GTID в бинарном логе другого сервера даст тот же результат.
Это влечёт за собой определённую ответственность пользователя. Репликация MariaDB GTID полностью асинхронна и полностью гибкая в плане конфигурации. Это позволяет использовать её в таких случаях, где предположение об одинаковом порядке следования событий в бинарном логе на всех серверах не выполняется. В таких случаях, при изменении первичного сервера, GTID по-прежнему будет пытаться продолжить с точки текущего GTID в новом бинарном логе.
Наиболее распространённый способ, когда порядок бинарного лога различается между серверами, заключается в том, что пользователь/DBA вносит изменения непосредственно на сервере реплики (и эти изменения записываются в бинарный лог реплики). Это приводит к событиям в бинарном логе реплики, которые отсутствуют на первичном сервере или на других репликах. Этого можно избежать, установив переменную сессии sql_log_bin в значение false во время таких обновлений, чтобы они не попадали в бинарный лог.
В идеале следует избегать любых различий в бинарных логах между серверами. Тем не менее, репликация MariaDB разработана для максимальной гибкости, и могут быть веские причины для временного внесения таких различий. В этом случае необходимо просто понять, что позиция GTID — это единственная точка в каждом потоке бинарного лога (по одному на каждый домен репликации), и как это влияет на конкретную конфигурацию пользователя.
Различия также могут возникнуть, когда два первичных сервера активны одновременно в иерархии репликации. Это происходит при использовании многопервичного кольца. Но это также может произойти в простой схеме первичный-реплика при переключении на новый первичный сервер, если изменения на старом первичном сервере не были полностью реплицированы на все сервера реплик перед переключением первичного сервера. Обычно, чтобы переключить первичный сервер, сначала необходимо остановить записи на старом первичном сервере, затем дождаться, пока все изменения будут реплицированы на новый первичный сервер, и только после этого следует начать записи на новом первичном сервере. Целенаправленное использование нескольких активных первичных серверов также поддерживается, это описывается в следующей секции.
Режим строгости GTID (GTID strict mode) можно использовать для обеспечения идентичности бинарных логов на всех серверах. При включении этого режима большинство действий, которые могут привести к различиям, будут отклонены с ошибкой.
Использование с многоисточниковой репликацией и другими многопервичными схемами
Глобальный идентификатор транзакции MariaDB поддерживает одновременную активность нескольких первичных серверов. Обычно это происходит при многоисточниковой репликации или многопервичных кольцах.
В таких схемах каждый активный первичный сервер должен быть настроен со своим уникальным идентификатором домена репликации gtid_domain_id. В таком случае бинарный лог, по сути, будет состоять из нескольких независимых потоков, по одному на каждый активный первичный сервер. В пределах одного домена репликации порядок бинарного лога всегда одинаков на каждом сервере. Но два разных потока могут чередоваться по-разному в бинарных логах разных серверов.
Позиция GTID данной реплики тогда не является единственным GTID. Вместо этого она становится GTID последней группы событий, применённой для каждого значения идентификатора домена, фактически позицией, достигнутой в каждом потоке бинарного лога. Когда реплика подключается к первичному серверу, она может продолжить с одного потока в другой позиции бинарного лога, чем с другого потока. Поскольку порядок внутри одного потока согласован на всех серверах, этого достаточно, чтобы всегда иметь возможность продолжить репликацию в правильной точке на любом новом первичном сервере.
Идентификаторы доменов назначаются DBA в соответствии с потребностями приложения. Значение по умолчанию для @@GLOBAL.gtid_domain_id — 0. Это подходит для большинства схем репликации, где активен только один первичный сервер. Сервер MariaDB никогда сам не будет вводить новые значения domain_id в бинарный лог.
При использовании многоисточниковой репликации, где одна реплика подключается к нескольким первичным серверам одновременно, каждый такой первичный сервер должен быть настроен со своим уникальным идентификатором домена.
Аналогично, в топологии многопервичного кольца, где все первичные серверы обновляются приложением одновременно (с некоторым механизмом предотвращения конфликтов), для каждого сервера должен быть настроен уникальный идентификатор домена (в многопервичном кольце, где приложение следит за тем, чтобы выполнять обновления только на одном первичном сервере одновременно, достаточно одного идентификатора домена).
Обычно сервер реплики не должен получать прямые обновления (так как это создаёт различия в бинарных логах по сравнению с первичным сервером). Поэтому значение gtid_domain_id, установленное на сервере реплики, не имеет значения, хотя может быть целесообразно сделать его таким же, как у первичного сервера (если не используется многопервичная схема), чтобы упростить повышение реплики до нового первичного сервера. Конечно, если реплика сама является активным первичным сервером, как в многопервичном кольце, идентификатор домена должен быть установлен в соответствии с ролью сервера как активного первичного.
Обратите внимание, что идентификатор домена и идентификатор сервера — это разные понятия. Можно использовать разные идентификаторы доменов на каждом сервере, но обычно это нежелательно. Это усложняет понимание и работу с текущей позицией GTID (@@global.gtid_slave_pos) и теряет концепцию одного упорядоченного потока бинарного лога на всех серверах. Рекомендуется настроить столько идентификаторов доменов, сколько первичных серверов активно обновляется приложением в данный момент.
Неправильная настройка идентификаторов доменов (например, отсутствие настройки) сама по себе не является ошибкой. Например, это типично в сценарии обновления, где многопервичное кольцо, использующее версию 5.5, обновляется до версии 10.0. Кольцо продолжит работать так же, как и раньше, даже если всё настроено на использование идентификатора домена по умолчанию 0. Даже возможно использовать GTID для репликации между серверами. Однако необходимо соблюдать осторожность при переключении реплики на другой первичный сервер. Если порядок бинарного лога между старым и новым первичным сервером отличается, то одной позиции GTID для начала репликации в бинарном логе нового первичного сервера может быть недостаточно.
Удаление неиспользуемых доменов
FLUSH BINARY LOGS DELETE_DOMAIN_ID=(list-of-domains) может быть использовано для удаления устаревших доменов GTID из состояния бинарного лога сервера. Для успешного выполнения этой команды ни одна группа событий из указанных доменов GTID не должна присутствовать в существующих файлах бинарного лога. Если они всё ещё существуют, их необходимо очистить перед выполнением этой команды.
Если команда выполняется успешно, то она также производит перенос бинарного лога.
Старые домены всё ещё будут отображаться в gtid_io_pos. Чтобы избавиться от них, можно остановить реплику и выполнить команду на реплике:
SET gtid_slave_pos="<position with domains removed>"
Новая синтаксис для глобального идентификатора транзакции
CHANGE MASTER
CHANGE MASTER имеет новый параметр, master_use_gtid=[current_pos|slave_pos|no]. При включении (установлено в current_pos или slave_pos) реплика подключается к мастеру, используя позицию GTID. При отключении (установлено в "no") используется старая позиция файла/смещения бинарного лога для определения точки начала репликации при подключении. В отличие от старого стиля, когда GTID включен, значения параметров MASTER_LOG_FILE и MASTER_LOG_POS не обновляются по мере получения события в файле master_info_file.
Значение master_use_gtid сохраняется при перезапуске сервера (в master.info). Текущее значение можно увидеть как поле Using_Gtid в выводе команды SHOW SLAVE STATUS.
Подробное сравнение параметров current_pos и slave_pos см. в разделе Использование глобальных идентификаторов транзакций
START SLAVE UNTIL master_gtid_pos=xxx
При запуске репликации с помощью START SLAVE можно запросить, чтобы реплика выполнялась только до достижения определённой позиции GTID. После достижения этой позиции реплика остановится.
Синтаксис для этого:
START SLAVE UNTIL master_gtid_pos = <GTID position>
Реплика начнёт репликацию с текущей позиции GTID, выполнится до и включая событие с указанным GTID, а затем остановится. Обратите внимание, что это останавливает как поток IO, так и поток SQL (в отличие от START SLAVE UNTIL MASTER_LOG_FILE/MASTER_LOG_POS, который останавливает только поток SQL).
Если указано несколько GTID, то они должны быть с различными идентификаторами домена репликации, например:
START SLAVE UNTIL master_gtid_pos = "1-11-100,2-21-50"
При нескольких доменах в условии UNTIL каждый домен выполняется только до и включая указанную позицию, поэтому разные домены могут останавливаться в разных местах в бинарном логе (каждый домен возобновится с остановленной позиции при следующем запуске реплики).
Если идентификатор домена вообще не указан в условии UNTIL, это означает, что домен останавливается немедленно, ничего не реплицируется из этого домена. В частности, указание пустой строки остановит реплику немедленно.
При использовании START SLAVE UNTIL master_gtid_pos = XXX, если позиция UNTIL присутствует в бинарном логе первичного сервера, то начальная позиция может отсутствовать на первичном сервере. В этом случае репликация для соответствующих доменов останавливается немедленно.
Обе реплицирующие потоки должны быть остановлены до использования UNTIL master_gtid_pos, иначе произойдет ошибка. Также ошибка возникает, если реплика не настроена для использования GTID (CHANGE MASTER TO master_use_gtid=current_pos|slave_pos). Кроме того, оба потока должны быть запущены одновременно; опции IO_THREAD или SQL_THREAD не могут использоваться для запуска только одного из них.
START SLAVE UNTIL master_gtid_pos=XXX особенно полезен для продвижения нового первичного сервера среди набора реплик, когда старый мастер выходит из строя, и реплики могут достичь разных позиций в бинарном журнале старого мастера. Новый первичный сервер должен опережать все другие реплики, чтобы избежать потери событий. Это можно достичь, выбрав один сервер, скажем, S1, и выполнив репликацию всех отсутствующих событий с других серверов S2, S3, ..., Sn:
CHANGE MASTER TO master_host="S2";
START SLAVE UNTIL master_gtid_pos = "<S2 GTID position>";
...
CHANGE MASTER TO master_host="Sn";
START SLAVE UNTIL master_gtid_pos = "<Sn GTID position>";
После этого S1 будет содержать все события, присутствующие на любом из серверов. Теперь его можно выбрать в качестве нового первичного сервера, а все остальные серверы будут настроены на репликацию с него.
BINLOG_GTID_POS().
Функция BINLOG_GTID_POS() принимает на вход позицию бинарного журнала старого формата в виде имени файла и смещения в файле. Она ищет позицию в текущем бинарном журнале и возвращает строковое представление соответствующей позиции GTID. Если позиция не найдена в текущем бинарном журнале, возвращается NULL.
MASTER_GTID_WAIT
Функция MASTER_GTID_WAIT полезна в репликации для управления синхронизацией мастер/реплики и блокирует выполнение, пока реплика не прочитает и не применит все обновления до указанной позиции в журнале мастера. Подробности см. в MASTER_GTID_WAIT.
Переменные системы
gtid_slave_pos
Эта переменная системы содержит GTID последней транзакции, применённой к базе данных реплицирующими потоками сервера для каждой области репликации. Значение этой переменной автоматически обновляется всякий раз, когда реплицирующий поток применяет группу событий. Значение этой переменной также может быть изменено пользователем, чтобы изменить позицию GTID реплицирующих потоков.
При использовании многоисточниковой репликации одна и та же позиция GTID используется всеми подключениями реплик. В этом случае разные первичные серверы должны использовать разные области репликации, настроив разные значения gtid_domain_id. Если один первичный сервер использовал значение gtid_domain_id 1, а другой — значение gtid_domain_id 2, то любые реплики, реплицирующие с обоих первичных серверов, будут иметь GTIDs с обоими значениями gtid_domain_id в gtid_slave_pos.
Значение этой переменной может быть изменено вручную с помощью SET GLOBAL, но предварительно все реплицирующие потоки должны быть остановлены с помощью STOP SLAVE. Например:
STOP ALL SLAVES; SET GLOBAL gtid_slave_pos = "1-10-100,2-20-500"; START ALL SLAVES;
Значение этой переменной может быть сброшено путём присвоения ей пустой строки. Например:
SET GLOBAL gtid_slave_pos = '';
Позицию GTID, определённую gtid_slave_pos, можно использовать в качестве начальной позиции репликации, установив MASTER_USE_GTID=slave_pos при настройке реплики с помощью команды CHANGE MASTER TO. В качестве альтернативы можно использовать переменную системы gtid_current_pos как начальную позицию репликации.
Если пользователь устанавливает значение переменной gtid_slave_pos, и gtid_binlog_pos содержит более поздние GTIDs для определённых областей репликации, то gtid_current_pos будет содержать GTIDs из gtid_binlog_pos для этих областей репликации. Для защиты пользователей в этом сценарии, если пользователь устанавливает значение переменной gtid_slave_pos до позиции GTID, которая отстаёт от позиции GTID в gtid_binlog_pos, сервер выдаст предупреждение.
Это может помочь защитить пользователя, когда реплика настроена на использование gtid_current_pos в качестве позиции репликации. Это также может помочь защитить пользователя, когда сервер был откачен для перезапуска репликации с более ранней точки во времени, но пользователь забыл сбросить gtid_binlog_pos с помощью RESET MASTER.
Система mysql.gtid_slave_pos используется для хранения содержимого global.gtid_slave_pos и сохранения его после перезапуска.
- Командная строка: Нет
- Область: Глобальная
- Динамическая: Да
-
Тип данных:
string - Значение по умолчанию: Null
gtid_binlog_pos
Эта переменная содержит GTID последней группы событий, записанной в бинарный журнал для каждой области репликации.
Обратите внимание, что когда бинарный журнал пустой (например, при свежей установке или после RESET MASTER), нет записанных групп событий в любой области репликации, поэтому в этом случае значение gtid_binlog_pos будет пустой строкой.
Значение является только для чтения, но оно обновляется каждый раз, когда оператор DML или DDL записывается в бинарный журнал. Значение можно сбросить, выполнив RESET MASTER, что также удалит все бинарные журналы. Однако обратите внимание, что RESET MASTER не сбрасывает также gtid_slave_pos. Поскольку gtid_current_pos — это объединение gtid_slave_pos и gtid_binlog_pos, это означает, что новые GTIDs, добавленные к gtid_binlog_pos, могут отставать от тех, что в gtid_current_pos, если gtid_slave_pos содержит GTIDs в той же области с более высокими порядковыми номерами. Если вы хотите сбросить gtid_current_pos для определённой области GTID в таких случаях, вам также нужно изменить gtid_slave_pos помимо выполнения RESET MASTER. См. gtid_slave_pos для информации о том, как изменить его значение.
- Командная строка: Нет
- Область: Глобальная
- Динамическая: Только чтение
-
Тип данных:
string - Значение по умолчанию: Null
gtid_binlog_state
Переменная gtid_binlog_state содержит внутреннее состояние бинарного журнала. Состояние состоит из последнего GTID, когда-либо записанного в бинарный журнал для каждой комбинации domain_id и server_id. Эта информация используется первичным сервером для определения того, был ли данный GTID записан в бинарный журнал в прошлом, даже если он был позже удалён из-за очистки бинарного журнала. Для каждой domain_id последняя запись в @@gtid_binlog_state — это последний GTID, записанный в бинарный журнал, то есть это значение, которое появляется в @@gtid_binlog_pos.
Обычно это внутреннее состояние не нужно пользователям, поскольку @@gtid_binlog_pos в большинстве случаев более полезно. Основное использование @@gtid_binlog_state — восстановление состояния бинарного журнала после RESET MASTER (или, что эквивалентно, если файлы бинарного журнала потеряны). Если значение @@gtid_binlog_state сохраняется перед RESET MASTER и восстанавливается после него, первичный сервер сохранит информацию о прошлом, так же как если бы использовалась PURGE BINARY LOGS (конечно, фактические события в бинарных журналах всё ещё удаляются).
Обратите внимание, что для установки значения @@gtid_binlog_state бинарный журнал должен быть пустым, то есть он не должен содержать никаких событий GTID, а предыдущее значение @@gtid_binlog_state должно быть пустой строкой. Если нет, то сначала необходимо выполнить RESET MASTER, чтобы стереть бинарный журнал.
Значение @@gtid_binlog_state сохраняется сервером при перезапуске, записав файл MASTER-BIN.state, где MASTER-BIN — это базовое имя набора бинарных журналов, установленное опцией --log-bin. Этот файл записывается при завершении работы сервера и повторно считывается при следующем запуске сервера. (В случае сбоя сервера данные в MASTER-BIN.state некорректны, и сервер вместо этого восстанавливает правильное значение во время восстановления после сбоя бинарного журнала, сканируя файлы бинарного журнала и записывая каждый найденный GTID).
Для полноты, обратите внимание, что установка @@gtid_binlog_state внутренне выполняет RESET MASTER. Обычно это незаметно, так как его можно изменить только тогда, когда бинарный журнал пуст от событий GTID. Однако если выполнить его, например, сразу после обновления до MariaDB 10, возможно, бинарный журнал не пустой, но без событий GTID, в этом случае все такие события будут удалены, как если бы был выполнен RESET MASTER.
- Командная строка: Нет
- Область: Глобальная
- Динамическая: Да
-
Тип данных:
string - Значение по умолчанию: Null
gtid_current_pos
Эта переменная системы содержит GTID последней транзакции, применённой к базе данных для каждой области репликации.
Значение этой переменной строится из значений системных переменных gtid_binlog_pos и gtid_slave_pos. Она получает GTIDs транзакций, выполненных локально, из значения переменной gtid_binlog_pos. Она получает GTIDs реплицированных транзакций из значения переменной gtid_slave_pos.
Для каждой области репликации, если server_id соответствующего GTID в gtid_binlog_pos равен собственному server_id сервера, и порядковый номер выше, чем соответствующий GTID в gtid_slave_pos, то GTID из gtid_binlog_pos будет использоваться. В противном случае для этой области будет использоваться GTID из gtid_slave_pos.
GTID из gtid_binlog_pos, в которых server_id GTID не равен собственному server_id сервера, фактически игнорируются. Если gtid_binlog_pos содержит GTID для данного репликации домена, но server_id GTID не равен собственному server_id сервера, и gtid_slave_pos не содержит GTID для этого домена репликации, то gtid_current_pos не будет содержать никаких GTID для этого репликации домена.
Таким образом, gtid_current_pos содержит последний выполненный на сервере GTID, будь то в качестве первичного или реплики.
Позиция GTID, определенная gtid_current_pos, может быть использована в качестве начальной позиции репликации реплики путем установки MASTER_USE_GTID=current_pos при конфигурации реплики с помощью оператора CHANGE MASTER TO. В качестве альтернативы, системная переменная gtid_slave_pos также может быть использована в качестве начальной позиции репликации реплики.
Значение gtid_current_pos является только для чтения, но оно обновляется всякий раз, когда транзакция записывается в бинарный журнал и/или реплицируется потоком реплики, а GTID этой транзакции считается более новым, чем текущий GTID для этого домена. Правила определения, будет ли GTID считаться более новым, см. выше.
Если вам нужно сбросить значение, см. примечания по сбросу gtid_slave_pos и gtid_binlog_pos, так как gtid_current_pos формируется из значений этих переменных.
- Командная строка: Нет
- Область: Глобально
- Динамический: Только для чтения
-
Тип данных:
string - По умолчанию: Null
gtid_strict_mode
Режим строгости GTID — это необязательная настройка, которая может использоваться для помощи администратору базы данных в соблюдении строгих правил по поддержанию идентичности бинарных логов на нескольких серверах, реплицирующих с помощью глобального идентификатора транзакции.
При включенном режиме строгости GTID включены некоторые дополнительные ошибки для ситуаций, которые в противном случае могут вызвать различия между бинарными логами на разных серверах в иерархии репликации:
- Если сервер реплики пытается реплицировать GTID с номером последовательности меньше, чем уже есть в бинарном журнале для этого репликации домена, поток SQL останавливается с ошибкой (это указывает на дополнительную транзакцию в журнале реплики, отсутствующую на первичном сервере).
- Аналогично, попытка вручную добавить GTID с меньшим номером последовательности (путем установки
@@SESSION.gtid_seq_no) отклоняется с ошибкой. - Если реплика пытается подключиться, начиная с GTID, отсутствующего в журнале бинарных логов первичного сервера, это ошибка в режиме строгости GTID, даже если GTID существует с более высоким номером последовательности (это указывает на GTID на реплике, отсутствующей на первичном сервере). Обратите внимание, что эта ошибка контролируется настройкой режима строгости GTID на сервере подключаемой реплики.
Режим GTID отключен по умолчанию; это необходимо для сохранения обратной совместимости с существующими конфигурациями репликации (более старые версии сервера не применяли режим строгости для порядка бинарных логов). Глобальный идентификатор транзакции разработан для корректной работы даже при отключенном режиме строгости. Однако при включенном режиме строгости семантика проще и поэтому легче понять, так как порядок бинарных логов всегда идентичен на всех серверах, а номера последовательностей всегда строго возрастают в каждом домене репликации. Это также может облегчить автоматизацию скриптов для больших конфигураций репликации.
При включенном режиме строгости GTID реплика остановится с ошибкой при возникновении проблемы. Это позволяет администратору базы данных узнать о проблеме и принять корректирующие действия, чтобы избежать подобных проблем в будущем. Один из способов восстановления после такой ошибки — временно отключить режим строгости GTID на реплике, чтобы иметь возможность реплицировать за проблемой (возможно, с использованием START SLAVE UNTIL master_gtid_pos=XXX).
-
Командная строка:
--gtid-strict-mode[={0|1}] - Область: Глобально
- Динамический: Да
-
Тип данных:
boolean -
По умолчанию:
Off
gtid_domain_id
- Описание: Эта переменная используется для определения, для какого домена репликации новые GTID регистрируются на первичном сервере. Подробности см. в разделе Использование с репликацией с нескольких источников и другими конфигурациями с несколькими первичными серверами. Пользователь с привилегией SUPER также может установить эту переменную на уровне сеанса. Это используется mariadb-binlog для сохранения идентификатора домена событий GTID.
-
Командная строка:
--gtid-domain-id=# - Область: Глобально, Сеанс
- Динамический: Да
-
Тип данных:
numeric (32-bit unsigned integer) -
Значение по умолчанию:
0 -
Диапазон:
0до4294967295
last_gtid
- Описание: Содержит GTID, который был назначен последней транзакции или оператору, который был записан в бинарный журнал. Если бинарный журнал отключен или транзакция или оператор еще не выполнялись в сеансе, значение является пустой строкой.
- Область: Сеанс
- Динамический: Только для чтения
-
Тип данных:
string
server_id
- Описание: Server_id может быть установлен на уровне сеанса для изменения значения server_id, которое регистрируется в событиях бинарного журнала (как GTID, так и других событиях). Это используется mariadb-binlog для сохранения идентификатора сервера событий GTID.
- Область: Глобально, Сеанс
- Динамический: Да
- Тип данных: число (32-разрядное беззнаковое целое число)
gtid_seq_no
- Описание: gtid_seq_no может быть установлен на уровне сеанса для изменения номера последовательности, который регистрируется в следующем событии GTID. Переменная вместе с @@gtid_domain_id и @@server_id обычно используется mariadb-binlog для установки значения gtid транзакции, которая декодируется в выходные данные.
- Командная строка: Нет
- Область: Сеанс
- Динамический: Да
-
Тип данных:
numeric (64-bit unsigned integer) - По умолчанию: Null
gtid_ignore_duplicates
- Описание: При установке разрешается, чтобы разные первичные подключения в репликации с нескольких источников получали и обрабатывали группы событий с одинаковым GTID (при использовании режима GTID). Только один будет применен, остальные будут проигнорированы. В данном репликации домене только номер последовательности будет использован для определения, был ли данный GTID уже применён; это означает, что пользователю необходимо гарантировать, что номера последовательностей GTID строго возрастают. При gtid_ignore_duplicates=OFF дублируемое событие на основе идентификатора домена и номера последовательности будет выполнено.
-
Командная строка:
--gtid-ignore-duplicates=# - Область: Глобально
- Динамический: Да
-
Тип данных:
boolean -
По умолчанию:
OFF
gtid_pos_auto_engines
Эта переменная используется для включения нескольких версий таблицы mysql.gtid_slave_pos, по одной для каждого используемого движка хранилища транзакций. Это может улучшить производительность репликации, если сервер использует несколько различных движков хранилища в разных транзакциях.
Значение представляет собой список имён движков, разделенных запятыми (','). Репликация транзакций, использующих эти движки, автоматически создаст новые версии таблицы mysql.gtid_slave_pos в том же движке и будет использовать её для будущих транзакций (создание таблицы происходит в фоновом потоке). Это позволяет избежать введения меж-движковых транзакций для обновления позиции GTID. Для gtid_pos_auto_engines поддерживаются только движки хранилища транзакций (в настоящее время это InnoDB, TokuDB или MyRocks).
Переменную можно изменять динамически, но потоки SQL реплик должны быть остановлены при её изменении, и она вступит в силу при повторном запуске реплик.
При установке переменной в командной строке или в файле конфигурации можно указать движки, которые не включены на сервере. В таком случае сервер всё равно запустится, если, например, этот движок больше не используется. Попытка динамически установить неактивный движок на работающем сервере (с помощью SET GLOBAL gtid_pos_auto_engines) по-прежнему приведёт к ошибке.
Удаление движка хранилища из переменной не повлияет, после того как новые таблицы были созданы — пока эти таблицы обнаруживаются, они будут использоваться.
-
Командная строка:
--gtid-pos-auto-engines=value - Область: Глобально
- Динамический: Да
-
Тип данных:
string(список имён движков, разделенных запятыми) - По умолчанию: пустая
gtid_cleanup_batch_size
- Описание: Обычно не требует настройки. Сколько старых строк должно накопиться в таблице mysql.gtid_slave_pos, прежде чем фоновая задача начнёт их удалять. Можно увеличить для уменьшения количества подтверждений, если используется много разных движков с gtid_pos_auto_engines, или для уменьшения нагрузки на процессор, если используется большое количество разных gtid_domain_id. Можно уменьшить для уменьшения количества старых строк в таблице.
-
Командная строка:
--gtid-cleanup-batch-size=# - Область действия: Глобально
- Динамично: Да
-
Тип данных:
numeric -
Значение по умолчанию:
64 -
Диапазон:
0до2147483647 - Введено: MariaDB 10.4.1
См. также
- FLUSH двоичных журналов
© 2023 MariaDB
Licensed under the Creative Commons Attribution 3.0 Unported License and the GNU Free Documentation License.
https://mariadb.com/kb/en/gtid/