Spec-Zone.ru › MySQL 8.4

7.6.6.3 Использование маркеров версий

Перед использованием маркеров версий, установите их в соответствии с инструкциями в разделе раздел 7.6.6.2, «Установка или удаление маркеров версий».

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

  • Коллекция серверов MySQL, которые нужно управлять.

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

  • Клиентские приложения, которые обращаются к серверам для извлечения и обновления данных, выбирая серверы в соответствии с назначенными им целями. Например, клиент не должен отправлять обновление на только-для-чтения сервер.

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

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

    Если в какой-то момент приложению управления нужно изменить назначение сервера (например, изменить его с разрешения записи на только для чтения), оно изменяет список маркеров версий сервера и обновляет свой кэш.

  • Для повышения производительности клиентские приложения получают информацию из кэша от приложения управления, позволяя им избежать необходимости извлечения информации о назначении сервера для каждой инструкции. Основываясь на типе выполняемых инструкций (например, чтение по сравнению с записью), клиент выбирает подходящий сервер и подключается к нему.

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

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

Логика клиентской стороны для обнаружения ошибок маркеров версий и выбора нового сервера может быть реализована различными способами:

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

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

Следующий пример иллюстрирует предыдущую дискуссию в более конкретной форме.

При инициализации маркеров версий на заданном сервере список маркеров версий сервера пуст. Поддержание списка маркеров выполняется путем вызова функций. Для вызова любой из функций маркеров версий требуется привилегия VERSION_TOKEN_ADMIN (или устаревшая привилегия SUPER), поэтому изменение списка маркеров, как ожидается, будет осуществляться приложением управления или администратора, имеющим эту привилегию.

Предположим, что приложение управления взаимодействует с набором серверов, к которым клиенты обращаются для доступа к базам данных сотрудников и продуктов (названные emp и prod соответственно). Все серверы разрешено обрабатывать инструкции по получению данных, но только некоторые из них разрешено выполнять обновления баз данных. Для обработки этого на базе данных, приложение управления устанавливает список маркеров версий на каждом сервере. В списке маркеров для данного сервера имена маркеров представляют имена баз данных, а значения маркеров являются read или write в зависимости от того, должна ли база данных использоваться в режиме только для чтения или может принимать чтение и запись.

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

Для определения списка маркеров версий для сервера приложение управления вызывает функцию version_tokens_set(). (Также существуют функции для изменения и отображения списка маркеров, описанные позже.) Например, приложение может отправить эти инструкции на группу из трех серверов:

Сервер 1:

mysql> SELECT version_tokens_set('emp=read;prod=read');
+------------------------------------------+
| version_tokens_set('emp=read;prod=read') |
+------------------------------------------+
| 2 version tokens set.                    |
+------------------------------------------+

Сервер 2:

mysql> SELECT version_tokens_set('emp=write;prod=read');
+-------------------------------------------+
| version_tokens_set('emp=write;prod=read') |
+-------------------------------------------+
| 2 version tokens set.                     |
+-------------------------------------------+

Сервер 3:

mysql> SELECT version_tokens_set('emp=read;prod=write');
+-------------------------------------------+
| version_tokens_set('emp=read;prod=write') |
+-------------------------------------------+
| 2 version tokens set.                     |
+-------------------------------------------+

Список маркеров в каждом случае задается как список пар name=value, разделенных точкой с запятой. Результирующие значения списка маркеров приводят к следующим назначениям серверов:

  • Любой сервер принимает чтение для любой базы данных.

  • Только сервер 2 принимает обновления для базы данных emp.

  • Только сервер 3 принимает обновления для базы данных prod.

В дополнение к назначению списка маркеров версий каждому серверу, приложение управления также поддерживает кэш, который отражает назначения серверов.

Перед взаимодействием с серверами клиентское приложение связывается с приложением управления и получает информацию о назначении серверов. Затем клиент выбирает сервер на основе этих назначений. Предположим, что клиент хочет выполнить как чтение, так и запись в базе данных emp. Основываясь на предыдущих назначениях, подходит только сервер 2. Клиент подключается к серверу 2 и регистрирует свои требования к серверу, установив системную переменную version_tokens_session:

mysql> SET @@SESSION.version_tokens_session = 'emp=write';

Для последующих инструкций, отправленных клиентом на сервер 2, сервер сравнивает свой собственный список маркеров версий со списком клиента, чтобы проверить их соответствие. Если это так, инструкции выполняются нормально:

mysql> UPDATE emp.employee SET salary = salary * 1.1 WHERE id = 4981;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT last_name, first_name FROM emp.employee WHERE id = 4981;
+-----------+------------+
| last_name | first_name |
+-----------+------------+
| Smith     | Abe        |
+-----------+------------+
1 row in set (0.01 sec)

Несоответствия между списком маркеров версий сервера и клиента могут возникать двумя способами:

  • Имя маркера в значении version_tokens_session отсутствует в списке маркеров сервера. В этом случае возникает ошибка.

  • Значение маркера в значении version_tokens_session отличается от значения соответствующего маркера в списке маркеров сервера. В этом случае возникает ошибка.

Пока назначение сервера 2 не изменится, клиент продолжает использовать его для чтения и записи. Но предположим, что приложение управления хочет изменить назначение сервера, чтобы записи для базы данных emp должны отправляться на сервер 1, а не на сервер 2. Для этого оно использует version_tokens_edit() для изменения значения маркера emp на двух серверах (и обновляет свой кэш назначений серверов):

Сервер 1:

mysql> SELECT version_tokens_edit('emp=write');
+----------------------------------+
| version_tokens_edit('emp=write') |
+----------------------------------+
| 1 version tokens updated.        |
+----------------------------------+

Сервер 2:

mysql> SELECT version_tokens_edit('emp=read');
+---------------------------------+
| version_tokens_edit('emp=read') |
+---------------------------------+
| 1 version tokens updated.       |
+---------------------------------+

version_tokens_edit() изменяет указанные маркеры в списке маркеров сервера и оставляет другие маркеры неизменными.

При следующем отправлении клиентом инструкции на сервер 2, его собственный список маркеров больше не соответствует списку маркеров сервера, и возникает ошибка:

mysql> UPDATE emp.employee SET salary = salary * 1.1 WHERE id = 4982;
ERROR 3136 (42000): Version token mismatch for emp. Correct value read

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

Примечание

Каждый клиент должен сотрудничать с маркеры версий, отправляя только инструкции, соответствующие списку маркеров, который он регистрирует на определенном сервере. Например, если клиент регистрирует список маркеров 'emp=read', в маркеры версий нет ничего, что могло бы помешать клиенту отправлять обновления для базы данных emp. Клиент сам должен воздержаться от этого.

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

  • Взять общую блокировку для каждого имени маркера в списке маркеров клиента (то есть в значении version_tokens_session)

  • Выполнить сравнение между списками маркеров сервера и клиента

  • Выполнить инструкцию или сгенерировать ошибку в зависимости от результата сравнения

  • Освободить блокировки

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

В предыдущем примере используются лишь некоторые функции из библиотеки плагина Version Tokens, но их больше. Одна группа функций позволяет управлять и просматривать список маркеров версий на сервере. Другая группа функций позволяет блокировать и разблокировать маркеры версий.

Эти функции позволяют создавать, изменять, удалять и просматривать список маркеров версий на сервере:

  • version_tokens_set() полностью заменяет текущий список и присваивает новый. Аргумент представляет собой список пар имя-значение, разделённых точкой с запятой.

  • version_tokens_edit() позволяет выполнять частичные изменения текущего списка. Она может добавлять новые маркеры или изменять значения существующих маркеров. Аргумент представляет собой список пар имя-значение, разделённых точкой с запятой.

  • version_tokens_delete() удаляет маркеры из текущего списка. Аргумент — список имён маркеров, разделённых точкой с запятой.

  • version_tokens_show() отображает текущий список маркеров. Не принимает аргументов.

Каждая из этих функций, при успешном выполнении, возвращает двоичную строку, указывающую, какое действие произошло. Следующий пример устанавливает список маркеров сервера, изменяет его, добавив новый маркер, удаляет некоторые маркеры и отображает получившийся список маркеров:

mysql> SELECT version_tokens_set('tok1=a;tok2=b');
+-------------------------------------+
| version_tokens_set('tok1=a;tok2=b') |
+-------------------------------------+
| 2 version tokens set.               |
+-------------------------------------+
mysql> SELECT version_tokens_edit('tok3=c');
+-------------------------------+
| version_tokens_edit('tok3=c') |
+-------------------------------+
| 1 version tokens updated.     |
+-------------------------------+
mysql> SELECT version_tokens_delete('tok2;tok1');
+------------------------------------+
| version_tokens_delete('tok2;tok1') |
+------------------------------------+
| 2 version tokens deleted.          |
+------------------------------------+
mysql> SELECT version_tokens_show();
+-----------------------+
| version_tokens_show() |
+-----------------------+
| tok3=c;               |
+-----------------------+

Возникают предупреждения, если список маркеров имеет неправильный формат:

mysql> SELECT version_tokens_set('tok1=a; =c');
+----------------------------------+
| version_tokens_set('tok1=a; =c') |
+----------------------------------+
| 1 version tokens set.            |
+----------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 42000
Message: Invalid version token pair encountered. The list provided
         is only partially updated.
1 row in set (0.00 sec)

Как упоминалось ранее, маркеры версий определяются с помощью списка пар имя-значение, разделённых точкой с запятой. Рассмотрим такое обращение к version_tokens_set():

mysql> SELECT version_tokens_set('tok1=b;;; tok2= a = b ; tok1 = 1\'2 3"4')
+---------------------------------------------------------------+
| version_tokens_set('tok1=b;;; tok2= a = b ; tok1 = 1\'2 3"4') |
+---------------------------------------------------------------+
| 3 version tokens set.                                         |
+---------------------------------------------------------------+

Плагин Version Tokens интерпретирует аргумент следующим образом:

  • Пробелы вокруг имён и значений игнорируются. Пробелы внутри имён и значений разрешены. (Для version_tokens_delete(), который принимает список имён без значений, пробелы вокруг имён игнорируются.)

  • Механизма цитирования нет.

  • Порядок маркеров не важен, за исключением того, что если список маркеров содержит несколько экземпляров имени данного маркера, последнее значение имеет приоритет над предыдущими значениями.

С учётом этих правил, вызов version_tokens_set() выше приводит к списку маркеров с двумя маркерами: tok1 имеет значение 1'2 3"4, а tok2 имеет значение a = b. Для проверки этого, вызовите version_tokens_show():

mysql> SELECT version_tokens_show();
+--------------------------+
| version_tokens_show()    |
+--------------------------+
| tok2=a = b;tok1=1'2 3"4; |
+--------------------------+

Если список маркеров содержит два маркера, почему version_tokens_set() вернул значение 3 version tokens set? Это произошло потому, что исходный список маркеров содержал два определения для tok1, и второе определение заменило первое.

Функции обработки маркеров Version Tokens накладывают следующие ограничения на имена и значения маркеров:

  • Имена маркеров не могут содержать = или ; символов и имеют максимальную длину 64 символа.

  • Значения маркеров не могут содержать ; символов. Длина значений ограничена значением системной переменной max_allowed_packet.

  • Version Tokens обрабатывает имена и значения маркеров как двоичные строки, поэтому сравнения чувствительны к регистру.

Version Tokens также включает набор функций, позволяющих блокировать и разблокировать маркеры:

  • version_tokens_lock_exclusive() получает эксклюзивные блокировки маркеров версий. Принимает список одного или нескольких имён блокировок и значение таймаута.

  • version_tokens_lock_shared() получает общие блокировки маркеров версий. Принимает список одного или нескольких имён блокировок и значение таймаута.

  • version_tokens_unlock() освобождает блокировки маркеров версий (эксклюзивные и общие). Не принимает аргументов.

Каждая функция блокировки возвращает ненулевое значение при успехе. В противном случае возникает ошибка:

mysql> SELECT version_tokens_lock_shared('lock1', 'lock2', 0);
+-------------------------------------------------+
| version_tokens_lock_shared('lock1', 'lock2', 0) |
+-------------------------------------------------+
|                                               1 |
+-------------------------------------------------+

mysql> SELECT version_tokens_lock_shared(NULL, 0);
ERROR 3131 (42000): Incorrect locking service lock name '(null)'.

Блокировка с помощью функций блокировки Version Tokens — рекомендательная; приложения должны согласовать свои действия.

Можно заблокировать несуществующие имена маркеров. Это не создаёт маркеры.

Примечание

Функции блокировки Version Tokens основаны на службе блокировки, описанной в разделе 7.6.9.1 «Сервис блокировки», и поэтому имеют одинаковую семантику для общих и эксклюзивных блокировок. (Version Tokens использует встроенные в сервер процедуры службы блокировки, а не интерфейс функции службы блокировки, поэтому эти функции не нужно устанавливать для использования Version Tokens.) Блокировки, полученные Version Tokens, используют пространство имён службы блокировки version_token_locks. Блокировки службы блокировки можно отслеживать с помощью Performance Schema, поэтому это также верно для блокировок Version Tokens. Подробности см. в разделе мониторинга службы блокировки.

Для функций блокировки Version Tokens аргументы имён маркеров используются точно так, как указано. Окружающие пробелы не игнорируются, и = и ; символы разрешены. Это связано с тем, что Version Tokens просто передает имена маркеров для блокировки службе блокировки в неизменном виде.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/version-tokens-usage.html

Spec-Zone.ru

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