Spec-Zone.ru › MySQL 8.4

19.1.3.1 Формат и хранение GTID

Глобальный идентификатор транзакции (GTID) — это уникальный идентификатор, созданный и сопоставленный с каждой транзакцией, подтверждённой на сервере-источнике. Этот идентификатор уникален не только для сервера, на котором он был создан, но и для всех серверов в заданной топологии репликации.

Присвоение GTID различается для клиентских транзакций, которые подтверждаются на источнике, и реплицированных транзакций, которые воспроизводятся на реплике. При подтверждении клиентской транзакции на источнике ей присваивается новый GTID, при условии, что транзакция была записана в бинарный журнал. Клиентские транзакции гарантированно имеют монотонно возрастающие GTID без пробелов между сгенерированными числами. Если клиентская транзакция не записывается в бинарный журнал (например, потому что транзакция была отфильтрована или была транзакцией только чтения), ей не присваивается GTID на сервере-источнике.

Реплицированные транзакции сохраняют тот же самый GTID, что был присвоен транзакции на сервере-источнике. GTID присутствует до начала выполнения реплицированной транзакции и сохраняется даже если реплицированная транзакция не была записана в бинарный журнал на реплике или была отфильтрована на реплике. Система таблицы mysql.gtid_executed используется для сохранения присвоенных GTID всех транзакций, применённых на сервере MySQL, за исключением тех, которые хранятся в текущем активном файле бинарного журнала.

Функция автопропуска для GTID означает, что транзакция, подтверждённая на источнике, может быть применена не более одного раза на реплике, что помогает гарантировать согласованность. После того, как транзакция с заданным GTID была подтверждена на определённом сервере, любая попытка выполнить последующую транзакцию с тем же самым GTID игнорируется этим сервером. Ошибка не генерируется, и никакие операторы в транзакции не выполняются.

Если транзакция с заданным GTID начала выполняться на сервере, но ещё не подтверждена или не отменена, любая попытка начать одновременную транзакцию на сервере с тем же самым GTID блокируется. Сервер не начинает выполнять одновременную транзакцию и не возвращает управление клиенту. После того, как первая попытка транзакции подтверждается или отменяется, одновременные сессии, которые были заблокированы на том же самом GTID, могут продолжить работу. Если первая попытка была отменена, одна одновременная сессия продолжает пытаться выполнить транзакцию, а все другие одновременные сессии, которые были заблокированы на том же самом GTID, остаются заблокированными. Если первая попытка была подтверждена, все одновременные сессии перестают быть заблокированными и автоматически пропускают все операторы транзакции.

GTID представлен как пара координат, разделённых двоеточием (:), как показано здесь:

GTID = source_id:transaction_id

source_id идентифицирует сервер происхождения. Обычно для этой цели используется server_uuid источника. transaction_id — это порядковый номер, определяемый порядком подтверждения транзакции на источнике. Например, первая подтверждённая транзакция имеет transaction_id, равное 1, а десятая транзакция, подтверждённая на том же сервере происхождения, имеет transaction_id, равное 10. Невозможно, чтобы транзакция имела 0 в качестве порядкового номера в GTID. Например, двадцать третья транзакция, первоначально подтверждённая на сервере с UUID 3E11FA47-71CA-11E1-9E33-C80AA9429562, имеет следующий GTID:

3E11FA47-71CA-11E1-9E33-C80AA9429562:23

Верхний предел для порядковых номеров GTID на экземпляре сервера — это количество неотрицательных значений для 64-битного целого числа со знаком (263 - 1 или 9223372036854775807). Если на сервере заканчиваются GTID, он выполняет действие, указанное в binlog_error_action. При приближении экземпляра сервера к пределу выводится сообщение об ошибке.

MySQL 8.4 также поддерживает GTID с тегами. GTID с тегом состоит из трёх частей, разделённых двоеточиями, как показано здесь:

GTID = source_id:tag:transaction_id

В этом случае source_id и transaction_id определены ранее. tag — это строка, определяемая пользователем, используемая для идентификации определённой группы транзакций; см. описание переменной системы gtid_next для разрешенного синтаксиса. Пример: сто семнадцатая транзакция, первоначально подтверждённая на сервере с UUID ed102faf-eb00-11eb-8f20-0c5415bfaa1d и тегом Domain_1, имеет следующий GTID:

ed102faf-eb00-11eb-8f20-0c5415bfaa1d:Domain_1:117

GTID транзакции отображается в выводе из mysqlbinlog, и он используется для идентификации отдельной транзакции в таблицах состояния репликации Performance Schema, например, replication_applier_status_by_worker. Значение, хранящееся в переменной системы gtid_next (@@GLOBAL.gtid_next), представляет собой единственный GTID.

Наборы GTID

Набор GTID — это набор, состоящий из одного или нескольких отдельных GTID или диапазонов GTID. Наборы GTID используются в сервере MySQL различными способами. Например, значения, хранящиеся в переменных системы gtid_executed и gtid_purged, являются наборами GTID. Параметры START REPLICA UNTIL SQL_BEFORE_GTIDS и UNTIL SQL_AFTER_GTIDS могут быть использованы для обработки транзакций репликой только до первого GTID в наборе GTID или остановки после последнего GTID в наборе GTID. Встроенные функции GTID_SUBSET() и GTID_SUBTRACT() принимают наборы GTID в качестве входных данных.

Диапазон GTID, происходящих с одного сервера, можно свернуть в одно выражение, как показано здесь:

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5

В приведённом выше примере представлены первые пять транзакций, происходящие на сервере MySQL, у которого server_uuid равен 3E11FA47-71CA-11E1-9E33-C80AA9429562. Несколько отдельных GTID или диапазонов GTID, происходящих с одного сервера, также могут быть включены в одно выражение, причём GTID или диапазоны разделены двоеточиями, как в следующем примере:

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3:11:47-49

Набор GTID может включать любую комбинацию отдельных GTID и диапазонов GTID, а также GTID, происходящих с различных серверов. Этот пример показывает набор GTID, хранящийся в переменной системы gtid_executed (@@GLOBAL.gtid_executed) реплики, которая применила транзакции с более чем одного источника:

2174B383-5441-11E8-B90A-C80AA9429562:1-3, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19

При возвращении наборов GTID из переменных сервера UUID отсортированы в алфавитном порядке, а числовые интервалы объединены и отсортированы по возрастанию.

При построении набора GTID пользовательский тег обрабатывается как часть UUID. Это означает, что несколько GTID, происходящих с одного сервера и имеющих одинаковый тег, могут быть включены в одно выражение, как показано в этом примере:

3E11FA47-71CA-11E1-9E33-C80AA9429562:Domain_1:1-3:11:47-49

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

3E11FA47-71CA-11E1-9E33-C80AA9429562:Domain_1:1-3:15-21, 3E11FA47-71CA-11E1-9E33-C80AA9429562:Domain_2:8-52

Полный синтаксис набора GTID:

gtid_set:
    uuid_set [, uuid_set] ...
    | ''

uuid_set:
    uuid:[tag:]interval[:interval]...

uuid:
    hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh

h:
    [0-9|A-F]

tag:
    [a-z_][a-z0-9_]{0,31}

interval:
    m[-n]

    (m >= 1; n > m)
Таблица mysql.gtid_executed

GTID хранятся в таблице с именем gtid_executed в базе данных mysql. Строка в этой таблице содержит для каждого GTID или набора GTIDs, которые она представляет, UUID исходного сервера, пользовательский тег (если он есть) и начальные и конечные идентификаторы транзакций набора; для строки, ссылающейся только на один GTID, эти два последних значения одинаковы.

Таблица mysql.gtid_executed создаётся (если она ещё не существует) при установке или обновлении MySQL Server с помощью оператора CREATE TABLE, подобного показанному ниже:

CREATE TABLE gtid_executed (
  source_uuid CHAR(36) NOT NULL,
  interval_start BIGINT NOT NULL,
  interval_end BIGINT NOT NULL,
  gtid_tag CHAR(32) NOT NULL,
  PRIMARY KEY (source_uuid, gtid_tag, interval_start)
);
Предупреждение

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

Таблица mysql.gtid_executed предоставляется для внутреннего использования сервером MySQL. Она позволяет реплике использовать GTID, когда двоичное протоколирование отключено на реплике, и она позволяет сохранить состояние GTID, когда двоичные журналы были потеряны. Обратите внимание, что таблица mysql.gtid_executed очищается, если вы выполните оператор RESET BINARY LOGS AND GTIDS.

GTID хранятся в таблице mysql.gtid_executed только тогда, когда gtid_mode имеет значение ON или ON_PERMISSIVE. Если двоичное протоколирование отключено (log_bin имеет значение OFF) или если log_replica_updates отключено, сервер сохраняет GTID, принадлежащий каждой транзакции, вместе с транзакцией в буфере при завершении транзакции, а фоновый поток периодически добавляет содержимое буфера как одну или несколько записей в таблицу mysql.gtid_executed. Кроме того, таблица периодически сжимается с заданной пользователем скоростью, как описано в сжатии таблицы mysql.gtid_executed.

Если двоичное протоколирование включено (log_bin имеет значение ON), только для движка хранения InnoDB сервер обновляет таблицу mysql.gtid_executed так же, как и при отключении двоичного протоколирования или протоколирования обновлений реплики, сохраняя GTID для каждой транзакции в момент её завершения. Для других движков хранения сервер обновляет таблицу mysql.gtid_executed только при переключении двоичного журнала или выключении сервера. В эти моменты сервер записывает GTID всех транзакций, которые были записаны в предыдущий двоичный журнал, в таблицу mysql.gtid_executed.

Если к таблице mysql.gtid_executed нет доступа для записи, а двоичный журнал переключается по какой-либо причине, кроме достижения максимального размера файла (max_binlog_size), текущий двоичный журнал продолжает использоваться. Клиенту, запросившему переключение, возвращается сообщение об ошибке, и на сервере регистрируется предупреждение. Если к таблице mysql.gtid_executed нет доступа для записи и достигается значение max_binlog_size, сервер реагирует в соответствии с настройкой binlog_error_action. Если IGNORE_ERROR установлено, на сервере регистрируется ошибка, и двоичное протоколирование останавливается, а если ABORT_SERVER установлено, сервер завершается.

Сжатие таблицы mysql.gtid_executed

Со временем таблица mysql.gtid_executed может заполняться многими строками, ссылающимися на отдельные GTID, которые происходят из одного и того же сервера, имеют один и тот же тег GTID (если таковой имеется) и чьи идентификаторы транзакций образуют диапазон, подобный показанному здесь:

+--------------------------------------+----------------+--------------+----------+
| source_uuid                          | interval_start | interval_end | gtid_tag |
|--------------------------------------+----------------+--------------|----------+
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 31             | 31           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 32             | 32           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 33             | 33           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 34             | 34           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 35             | 35           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 36             | 36           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37             | 37           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 38             | 38           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 39             | 39           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 40             | 40           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 41             | 41           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 42             | 42           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 43             | 43           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 44             | 44           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 45             | 45           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 46             | 46           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 47             | 47           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 48             | 48           | Domain_1 |
...

Для экономии места сервер MySQL может периодически сжимать таблицу mysql.gtid_executed, заменяя каждый такой набор строк одной строкой, охватывающей весь интервал идентификаторов транзакций, например:

+--------------------------------------+----------------+--------------+----------+
| source_uuid                          | interval_start | interval_end | gtid_tag |
|--------------------------------------+----------------+--------------|----------+
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 31             | 35           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 36             | 39           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 40             | 43           | Domain_1 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 44             | 46           | Domain_2 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 47             | 48           | Domain_1 |
...

Сервер может выполнять сжатие с помощью специального фонового потока, названного thread/sql/compress_gtid_table. Этот поток не отображается в выводе SHOW PROCESSLIST, но его можно увидеть как строку в таблице threads, как показано здесь:

mysql> SELECT * FROM performance_schema.threads WHERE NAME LIKE '%gtid%'\G
*************************** 1. row ***************************
          THREAD_ID: 26
               NAME: thread/sql/compress_gtid_table
               TYPE: FOREGROUND
     PROCESSLIST_ID: 1
   PROCESSLIST_USER: NULL
   PROCESSLIST_HOST: NULL
     PROCESSLIST_DB: NULL
PROCESSLIST_COMMAND: Daemon
   PROCESSLIST_TIME: 1509
  PROCESSLIST_STATE: Suspending
   PROCESSLIST_INFO: NULL
   PARENT_THREAD_ID: 1
               ROLE: NULL
       INSTRUMENTED: YES
            HISTORY: YES
    CONNECTION_TYPE: NULL
       THREAD_OS_ID: 18677

Когда двоичное протоколирование включено на сервере, этот метод сжатия не используется, а вместо этого таблица mysql.gtid_executed сжимается при каждом переключении двоичного журнала. Однако, когда двоичное протоколирование отключено на сервере, поток thread/sql/compress_gtid_table ожидает, пока не будет выполнено заданное количество транзакций, затем просыпается для сжатия таблицы mysql.gtid_executed. Затем он снова ожидает, пока не произойдёт то же количество транзакций, после чего просыпается для повторного сжатия, повторяя этот цикл бесконечно. Количество транзакций, проходящих между сжатиями таблицы, а, следовательно, и скорость сжатия, контролируется значением системной переменной gtid_executed_compression_period. Установка этого значения в 0 означает, что поток никогда не просыпается, то есть этот явный метод сжатия не используется. Вместо этого сжатие происходит неявно по мере необходимости.

Транзакции InnoDB записываются в таблицу mysql.gtid_executed отдельным процессом от того, который используется для транзакций, связанных с движками хранения, отличными от InnoDB. Этот процесс контролируется другим потоком, innodb/clone_gtid_thread. Этот поток сохранения GTID собирает GTID группами, записывает их в таблицу mysql.gtid_executed, затем сжимает таблицу. Если на сервере есть смесь транзакций InnoDB и не-InnoDB транзакций, которые записываются в таблицу mysql.gtid_executed по отдельности, сжатие, выполняемое потоком compress_gtid_table, мешает работе потока сохранения GTID и может значительно замедлить его. По этой причине рекомендуется установить gtid_executed_compression_period в 0, чтобы поток compress_gtid_table никогда не активировался.

Значение по умолчанию для gtid_executed_compression_period равно 0, и все транзакции, независимо от движка хранения, записываются в таблицу mysql.gtid_executed потоком сохранения GTID.

При запуске экземпляра сервера, если gtid_executed_compression_period установлено ненулевым значением, и поток thread/sql/compress_gtid_table запущен, в большинстве конфигураций сервера выполняется явное сжатие таблицы mysql.gtid_executed. Сжатие инициируется запуском потока.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/replication-gtids-concepts.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API