Spec-Zone.ru › MySQL 9.2

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 — это номер последовательности, определяемый порядком подтверждения транзакции на источнике. Например, первая транзакция, которая была подтверждена, имеет 1 в качестве своего transaction_id, а десятая транзакция, которая была подтверждена на том же сервере происхождения, получает 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 9.2 также поддерживает 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 или набора GTID, которые он представляет, 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-9.2-en/replication-gtids-concepts.html

Spec-Zone.ru

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