Spec-Zone.ru › MySQL 5.7

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

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

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

Реплицированные транзакции сохраняют тот же GTID, который был назначен транзакции на целевом сервере. GTID присутствует до начала выполнения реплицированной транзакции и сохраняется, даже если реплицированная транзакция не была записана в двоичный журнал на реплике или была отфильтрована на реплике. Таблица систем MySQL 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. Для GTID не может быть 0 в качестве порядкового номера. Например, двадцать третья транзакция, изначально завершенная на сервере с UUID 3E11FA47-71CA-11E1-9E33-C80AA9429562, имеет следующий GTID:

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

Максимальное значение порядкового номера для GTID на экземпляре сервера равно числу неотрицательных значений для 64-битного целого числа со знаком (2 в степени 63 минус 1, или 9 223 372 036 854 775 807). Если сервер исчерпывает GTID, он выполняет действие, указанное в binlog_error_action.

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 SLAVE 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:

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

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

uuid:
    hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh

h:
    [0-9|A-F]

interval:
    n[-n]

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

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

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

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

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

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

GTID хранятся в таблице mysql.gtid_executed только тогда, когда gtid_mode имеет значение ON или ON_PERMISSIVE. Точка хранения GTID зависит от того, включена или выключена двоичная запись:

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

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

    В случае непредвиденного завершения работы сервера набор GTID из текущего файла двоичного журнала не сохраняется в таблице mysql.gtid_executed. Эти GTID добавляются в таблицу из файла двоичного журнала во время восстановления. Исключением является случай, когда двоичная запись отключена при перезапуске сервера. В этом случае сервер не может получить доступ к файлу двоичного журнала для восстановления GTID, поэтому репликация не может быть начата.

    Когда двоичная запись включена, таблица mysql.gtid_executed не содержит полного списка GTID всех выполненных транзакций. Эта информация предоставляется глобальным значением системной переменной gtid_executed. Всегда используйте @@GLOBAL.gtid_executed, которая обновляется после каждого завершения транзакции, для представления состояния GTID сервера MySQL, и не запрашивайте таблицу mysql.gtid_executed.

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

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

+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
|--------------------------------------+----------------+--------------|
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37             | 37           |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 38             | 38           |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 39             | 39           |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 40             | 40           |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 41             | 41           |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 42             | 42           |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 43             | 43           |
...

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

+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
|--------------------------------------+----------------+--------------|
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37             | 43           |
...

Вы можете контролировать количество транзакций, которые могут пройти, прежде чем таблица будет сжата, а следовательно, и коэффициент сжатия, установив системную переменную gtid_executed_compression_period. Значение этой переменной по умолчанию равно 1000, что означает, что по умолчанию сжатие таблицы выполняется после каждой 1000 транзакций. Установка gtid_executed_compression_period в 0 предотвращает выполнение сжатия вообще, и вы должны быть готовы к потенциальному значительному увеличению потребления дискового пространства таблицей gtid_executed, если сделаете это.

Примечание

При включенном двоичном протоколировании значение gtid_executed_compression_period не используется, и таблица mysql.gtid_executed сжимается при каждом вращении двоичного протокола.

Сжатие таблицы mysql.gtid_executed выполняется выделенной фоновой нитью под названием 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

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

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

Spec-Zone.ru

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