Spec-Zone.ru › MySQL 8.4

19.1.3.8 Примеры хранимых функций для управления GTID

В этом разделе приведены примеры хранимых функций (см. главу 27, Хранимые объекты), которые вы можете создать, используя некоторые встроенные функции MySQL, предназначенные для работы с репликацией на основе GTID, перечисленные здесь:

  • GTID_SUBSET(): Показывает, является ли один набор GTID подмножеством другого.

  • GTID_SUBTRACT(): Возвращает GTID из одного набора GTID, которые отсутствуют в другом.

  • WAIT_FOR_EXECUTED_GTID_SET(): Ожидает, пока все транзакции в заданном наборе GTID не будут выполнены.

См. раздел 14.18.2, «Функции, используемые с глобальными идентификаторами транзакций (GTID)», для получения дополнительной информации о только что перечисленных функциях.

Обратите внимание, что в этих хранимых функциях используется команда разделителя для изменения разделителя оператора MySQL на вертикальную черту, например:

mysql> delimiter |

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

Эта функция возвращает ненулевое значение (true), если два набора GTID являются одним и тем же набором, даже если они отформатированы по-разному:

CREATE FUNCTION GTID_IS_EQUAL(gs1 LONGTEXT, gs2 LONGTEXT)
  RETURNS INT
  RETURN GTID_SUBSET(gs1, gs2) AND GTID_SUBSET(gs2, gs1)
|

Эта функция возвращает ненулевое значение (true), если два набора GTID не пересекаются:

CREATE FUNCTION GTID_IS_DISJOINT(gs1 LONGTEXT, gs2 LONGTEXT)
RETURNS INT
  RETURN GTID_SUBSET(gs1, GTID_SUBTRACT(gs1, gs2))
|

Эта функция возвращает ненулевое значение (true), если два набора GTID не пересекаются и sum является их объединением:

CREATE FUNCTION GTID_IS_DISJOINT_UNION(gs1 LONGTEXT, gs2 LONGTEXT, sum LONGTEXT)
RETURNS INT
  RETURN GTID_IS_EQUAL(GTID_SUBTRACT(sum, gs1), gs2) AND
         GTID_IS_EQUAL(GTID_SUBTRACT(sum, gs2), gs1)
|

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

CREATE FUNCTION GTID_NORMALIZE(gs LONGTEXT)
RETURNS LONGTEXT
  RETURN GTID_SUBTRACT(gs, '')
|

Эта функция возвращает объединение двух наборов GTID:

CREATE FUNCTION GTID_UNION(gs1 LONGTEXT, gs2 LONGTEXT)
RETURNS LONGTEXT
  RETURN GTID_NORMALIZE(CONCAT(gs1, ',', gs2))
|

Эта функция возвращает пересечение двух наборов GTID.

CREATE FUNCTION GTID_INTERSECTION(gs1 LONGTEXT, gs2 LONGTEXT)
RETURNS LONGTEXT
  RETURN GTID_SUBTRACT(gs1, GTID_SUBTRACT(gs1, gs2))
|

Эта функция возвращает симметрическую разность между двумя наборами GTID, то есть GTID, которые существуют в gs1, но не в gs2, а также GTID, которые существуют в gs2, но не в gs1.

CREATE FUNCTION GTID_SYMMETRIC_DIFFERENCE(gs1 LONGTEXT, gs2 LONGTEXT)
RETURNS LONGTEXT
  RETURN GTID_SUBTRACT(CONCAT(gs1, ',', gs2), GTID_INTERSECTION(gs1, gs2))
|

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

CREATE FUNCTION GTID_SUBTRACT_UUID(gs LONGTEXT, uuid TEXT)
RETURNS LONGTEXT
  RETURN GTID_SUBTRACT(gs, CONCAT(UUID, ':1-', (1 << 63) - 2))
|

Эта функция является обратной предыдущей; она возвращает только те GTID из набора GTID, которые происходят с сервера с указанным идентификатором (UUID).

CREATE FUNCTION GTID_INTERSECTION_WITH_UUID(gs LONGTEXT, uuid TEXT)
RETURNS LONGTEXT
  RETURN GTID_SUBTRACT(gs, GTID_SUBTRACT_UUID(gs, uuid))
|

Пример 19.1 Проверка актуальности реплики

Встроенные функции GTID_SUBSET() и GTID_SUBTRACT() можно использовать для проверки того, что реплика применила, как минимум, каждую транзакцию, примененную источником.

Для выполнения этой проверки с GTID_SUBSET() выполните следующую команду на реплике:

SELECT GTID_SUBSET(source_gtid_executed, replica_gtid_executed);

Если возвращаемое значение равно 0 (false), это означает, что некоторые GTID в source_gtid_executed отсутствуют в replica_gtid_executed, и что реплика еще не применила транзакции, примененные на источнике, что означает, что реплика не актуальна.

Для выполнения той же проверки с GTID_SUBTRACT() выполните следующую команду на реплике:

SELECT GTID_SUBTRACT(source_gtid_executed, replica_gtid_executed);

Эта команда возвращает любые GTID, которые есть в source_gtid_executed, но отсутствуют в replica_gtid_executed. Если возвращаются какие-либо GTID, это означает, что источник применил некоторые транзакции, которые реплика еще не применила, и, следовательно, реплика не актуальна.


Пример 19.2 Сценарий резервного копирования и восстановления

Хранимые функции GTID_IS_EQUAL(), GTID_IS_DISJOINT() и GTID_IS_DISJOINT_UNION() могут использоваться для проверки операций резервного копирования и восстановления, включающих несколько баз данных и серверов. В этом сценарии server1 содержит базу данных db1, а server2 содержит базу данных db2. Цель — скопировать базу данных db2 в server1, и результат на server1 должен быть объединением обеих баз данных. Используемый метод заключается в создании резервной копии server2 с помощью mysqldump, а затем восстановлении этой резервной копии на server1.

При условии, что mysqldump был запущен с --set-gtid-purged, установленным в ON или AUTO (по умолчанию), выход содержит оператор SET @@GLOBAL.gtid_purged, который добавляет набор gtid_executed из server2 в набор gtid_purged на server1. gtid_purged содержит GTID всех транзакций, которые были завершены на определенном сервере, но которые не существуют ни в одном файле бинарного журнала на сервере. При копировании базы данных db2 в server1 GTID транзакций, завершенных на server2, которые отсутствуют в файлах бинарного журнала на server1, должны быть добавлены в gtid_purged, чтобы server1 сделать набор полным.

Хранимые функции можно использовать для помощи в следующих этапах этого сценария:

  • Используйте GTID_IS_EQUAL(), чтобы убедиться, что операция резервного копирования вычислила правильный набор GTID для оператора SET @@GLOBAL.gtid_purged. На server2 извлеките этот оператор из вывода mysqldump и сохраните набор GTID в локальную переменную, например, в $gtid_purged_set. Затем выполните следующую команду:

    server2> SELECT GTID_IS_EQUAL($gtid_purged_set, @@GLOBAL.gtid_executed);
    

    Если результат равен 1, два набора GTID равны, и набор был вычислен правильно.

  • Используйте GTID_IS_DISJOINT(), чтобы убедиться, что набор GTID в выводе mysqldump не пересекается с набором gtid_executed на server1. Наличие идентичных GTID на обоих серверах приводит к ошибкам при копировании базы данных db2 в server1. Для проверки на server1 извлеките и сохраните gtid_purged из вывода в локальную переменную, как описано ранее, затем выполните следующую команду:

    server1> SELECT GTID_IS_DISJOINT($gtid_purged_set, @@GLOBAL.gtid_executed);
    

    Если результат равен 1, между двумя наборами GTID нет пересечения, поэтому дублирующихся GTID нет.

  • Используйте GTID_IS_DISJOINT_UNION(), чтобы убедиться, что операция восстановления привела к правильному состоянию GTID на server1. Перед восстановлением резервной копии на server1 получите существующий набор gtid_executed, выполнив следующую команду:

    server1> SELECT @@GLOBAL.gtid_executed;
    

    Сохраните результат в локальной переменной $original_gtid_executed, а также набор из gtid_purged в другую локальную переменную, как описано ранее. После восстановления резервной копии из server2 на server1 выполните следующую команду, чтобы проверить состояние GTID:

    server1> SELECT
          ->   GTID_IS_DISJOINT_UNION($original_gtid_executed,
          ->                          $gtid_purged_set,
          ->                          @@GLOBAL.gtid_executed);
    

    Если результат равен 1, хранимая функция проверила, что исходный набор gtid_executed из server1 ($original_gtid_executed) и добавленный набор gtid_purged из server2 ($gtid_purged_set) не пересекаются, и что обновленный набор gtid_executed на server1 теперь состоит из предыдущего набора gtid_executed из server1 плюс набора gtid_purged из server2, что является желаемым результатом. Убедитесь, что эта проверка выполняется до выполнения любых последующих транзакций на server1, в противном случае новые транзакции на gtid_executed приведут к ошибке.


Пример 19.3 Выбор наиболее актуальной реплики для ручного failover

Функция хранения данных GTID_UNION() может использоваться для определения наиболее актуальной реплики из набора реплик, для выполнения ручного failover после неожиданной остановки сервера источника. Если некоторые реплики испытывают задержку репликации, эта функция может быть использована для вычисления наиболее актуальной реплики без ожидания, пока все реплики применяют свои существующие релейные журналы, и, следовательно, для минимизации времени failover. Функция может вернуть объединение gtid_executed на каждой реплике со множеством транзакций, полученных репликой, которое записывается в таблицу Performance Schema replication_connection_status. Вы можете сравнить эти результаты, чтобы определить, запись транзакций какой реплики является наиболее актуальной, даже если не все транзакции были еще подтверждены.

На каждой реплике вычислите полную запись транзакций, выполнив следующую команду:

SELECT GTID_UNION(RECEIVED_TRANSACTION_SET, @@GLOBAL.gtid_executed)
    FROM performance_schema.replication_connection_status
    WHERE channel_name = 'name';

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


Пример 19.4 Проверка на наличие посторонних транзакций на реплике

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

Для реплики с одним источником выполните следующую команду, указав идентификатор исходного источника, который обычно совпадает с server_uuid:

SELECT GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed, server_uuid_of_source);

Если результат не пустой, возвращаемые транзакции являются дополнительными транзакциями, которые не исходили от назначенного источника.

Для реплики в многоисточниковой топологии включите идентификатор UUID каждого источника в вызов функции, как показано ниже:

SELECT
  GTID_SUBTRACT_UUID(GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed,
                                        server_uuid_of_source_1),
                                        server_uuid_of_source_2);

Если результат не пустой, возвращаемые транзакции являются дополнительными транзакциями, которые не исходили ни от одного из назначенных источников.


Пример 19.5 Проверка того, что сервер в топологии репликации является только для чтения

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

SELECT GTID_INTERSECTION_WITH_UUID(@@GLOBAL.gtid_executed, my_server_uuid);

Пример 19.6 Проверка дополнительной реплики в многоисточниковой репликации

Функция хранения данных GTID_INTERSECTION_WITH_UUID() может использоваться для определения того, применила ли реплика, подключенная к многоисточниковой настройке репликации, все транзакции, исходящие от одного конкретного источника. В этом сценарии source1 и source2 являются источниками и репликами и дублируют друг друга. source2 также имеет свою собственную реплику. Реплика также получает и применяет транзакции из source1, если source2 настроено с log_replica_updates=ON, но не делает этого, если source2 использует log_replica_updates=OFF. В любом случае, мы сейчас хотим только узнать, является ли реплика актуальной по отношению к source2. В этой ситуации GTID_INTERSECTION_WITH_UUID() может использоваться для идентификации транзакций, которые source2 генерировал, отбрасывая транзакции, которые source2 реплицировал из source1. Встроенная функция GTID_SUBSET() затем может быть использована для сравнения результата с набором gtid_executed на реплике. Если реплика актуальна по отношению к source2, то набор gtid_executed на реплике содержит все транзакции в пересекающемся наборе (транзакции, которые исходили от source2).

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

source2> SELECT @@GLOBAL.gtid_executed INTO @source2_gtid_executed;

source2> SELECT @@GLOBAL.server_uuid INTO @source2_server_uuid;

replica> SELECT @@GLOBAL.gtid_executed INTO @replica_gtid_executed;

Затем используйте GTID_INTERSECTION_WITH_UUID() и GTID_SUBSET() с этими переменными в качестве входных данных, как показано ниже:

SELECT
  GTID_SUBSET(
    GTID_INTERSECTION_WITH_UUID(@source2_gtid_executed,
                                @source2_server_uuid),
                                @replica_gtid_executed);

Идентификатор сервера из source2 (@source2_server_uuid) используется с GTID_INTERSECTION_WITH_UUID() для идентификации и возврата только тех GTID из набора GTID, которые исходили от source2, исключая те, которые исходили от source1. Полученный набор GTID затем сравнивается с набором всех выполненных GTID на реплике, используя GTID_SUBSET(). Если эта команда возвращает ненулевое значение (истина), все идентифицированные GTID из source2 (первый входной набор) также находятся в gtid_executed реплики, что означает, что реплика получила и выполнила все транзакции, исходящие от source2.


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

Spec-Zone.ru

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