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.