Spec-Zone.ru › MySQL 5.7

16.1.3.7 Примеры хранимых функций для работы с GTID

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

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

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

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

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

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

mysql> delimiter |

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

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

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

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

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

Эта функция возвращает ненулевое значение (истина), если два набора 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))
|

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

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

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

SELECT GTID_SUBSET(source_gtid_executed, replica_gtid_executed);

Если возвращаемое значение равно 0 (ложь), это означает, что некоторые 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, это означает, что источник применил некоторые транзакции, которые реплика еще не применила, и, следовательно, реплика не актуальна.


Пример 16.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 приведут к ошибке.


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

Хранимая функция GTID_UNION() может использоваться для определения наиболее актуальной реплики из набора реплик, чтобы выполнить ручное переключение после неожиданной остановки сервера-источника. Если некоторые реплики испытывают задержки репликации, эта хранимая функция может использоваться для вычисления наиболее актуальной реплики без ожидания применения всех существующих релейных логов всеми репликами, а следовательно, для минимизации времени переключения. Функция может вернуть объединение 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';

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


Пример 16.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);

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


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

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

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

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

Хранимая функция GTID_INTERSECTION_WITH_UUID() может использоваться для определения того, применила ли реплика, подключенная к репликации с несколькими источниками, все транзакции, исходящие от конкретного источника. В этом сценарии source2 и source1 являются как источниками, так и репликами и дублируют друг друга. source2 также имеет свою собственную реплику. Реплика также получает и применяет транзакции от source1, если source2 настроено так, но не делает этого, если 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-5.7-en/replication-gtids-functions.html

Spec-Zone.ru

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