MySQL Version Tokens

MySQL 5.7.8或更高版本的发行版包括版本令牌,该特性支持创建和同步服务器令牌,应用程序可以使用这些令牌来防止访问不正确或过时的数据。

版本令牌接口具有这些特征:
.版本令牌是由用作键或标识符的名称和一个值组成的对
.版本令牌可以被锁定。应用程序可以使用令牌锁向其他协作应用程序表明正在使用令牌,不应该修改它们。
.每个服务器都建立版本令牌列表;例如,指定服务器分配或操作状态。此外,与服务器通信的应用程序可以注册自己的令牌列表,这些令牌表示它需要服务器处于的状态。应用程序发送到不处于所需状态的服务器的SQL语句将产生错误。这是给应用程序的一个信号,它应该寻找另一个处于所需状态的服务器来接收SQL语句。

以下部分描述了版本令牌的组件,讨论了如何安装和使用它,并为其组件提供参考信息。

版本标识组件
名为version_token的服务器端插件持有与服务器关联的版本令牌列表,并订阅语句执行事件的通知。version_token插件使用审计插件API来监视来自客户端的传入语句,并将每个客户端特定于会话的版本令牌列表与服务器版本令牌列表进行匹配。如果存在匹配,插件允许语句通过,服务器继续处理它。否则,插件将向客户端返回一个错误,语句将失败。

一组用户定义函数(udf)提供了一个sql级别的API,用于操作和检查插件维护的服务器版本令牌列表。调用任何的令牌udf版本

系统变量允许客户端指定注册所需服务器状态的版本令牌列表。如果客户端发送语句时服务器处于不同的状态,则客户端接收到一个错误

安装或卸载版本令牌

这里介绍如何安装或卸载版本令牌,这些令牌是在包含插件和用户定义函数的插件库文件中实现的。有关安装或卸载插件和udf的一般信息要使服务器可用,插件库文件必须位于MySQL插件目录中(由plugin_dir系统变量命名的目录)。如果需要,在服务器启动时设置plugin_dir的值,告诉服务器插件目录的位置

插件库的基本名是version_token。文件名后缀因平台而异(例如,对于Unix和类Unix系统,.dll为Windows).

要安装版本令牌插件和udf,请使用install plugin并创建函数语句(根据需要调整.so后缀):

mysql> INSTALL PLUGIN version_tokens SONAME 'version_token.so';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    39
Current database: mysql

Query OK, 0 rows affected (0.07 sec)

mysql> CREATE FUNCTION version_tokens_set RETURNS STRING SONAME 'version_token.so';
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE FUNCTION version_tokens_show RETURNS STRING SONAME 'version_token.so';
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE FUNCTION version_tokens_edit RETURNS STRING SONAME 'version_token.so';
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE FUNCTION version_tokens_delete RETURNS STRING SONAME 'version_token.so';
CREATE FUNCTION version_tokens_lock_shared RETURNS STRING SONAME 'version_token.so';
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE FUNCTION version_tokens_lock_shared RETURNS STRING SONAME 'version_token.so';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION version_tokens_lock_exclusive RETURNS STRING SONAME 'version_token.so';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION version_tokens_unlock RETURNS STRING SONAME 'version_token.so';
Query OK, 0 rows affected (0.03 sec)

您必须安装udf来管理服务器的版本令牌列表,但是您还必须安装插件,因为没有它udf将无法正常工作。

如果在主复制服务器上使用插件和udf,也要将它们安装在所有从服务器上,以避免复制问题

如前所述,一旦安装完成,版本令牌插件和udf将一直保持安装状态,直到卸载为止。要删除它们,使用UNINSTALL插件和DROP FUNCTION语句:

mysql> uninstall plugin version_tokens;
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql> drop function version_tokens_set;
drop function version_tokens_show;
Query OK, 0 rows affected (0.02 sec)

mysql> drop function version_tokens_show;
drop function version_tokens_edit;
Query OK, 0 rows affected (0.00 sec)

mysql> drop function version_tokens_edit;
Query OK, 0 rows affected (0.00 sec)

mysql> drop function version_tokens_delete;
Query OK, 0 rows affected (0.01 sec)

mysql> drop function version_tokens_lock_shared;
Query OK, 0 rows affected (0.00 sec)

mysql> drop function version_tokens_lock_exclusive;
Query OK, 0 rows affected (0.00 sec)

mysql> drop function version_tokens_unlock;
Query OK, 0 rows affected (0.02 sec)

使用版本标记
版本令牌可能有用的一个场景是,系统访问MySQL服务器集合,但是需要通过监视它们并根据负载变化调整服务器分配来管理它们,以实现负载平衡。这样一个系统包括这些组件
.要管理的MySQL服务器集合
.与服务器通信并将它们组织成高可用性组的管理或管理应用程序。组有不同的用途,每个组中的服务器可能有不同的分配。某个组内的服务器的分配可以随时更改
.访问服务器以检索和更新数据的客户机应用程序,根据分配给它们的用途选择服务器。例如,客户端不应该向只读服务器发送更新

版本令牌允许根据分配对服务器访问进行管理,而不需要客户端重复查询服务器的分配
.管理应用程序执行服务器分配并在每个服务器上建立版本令牌以反映其分配。应用程序缓存此信息以提供对其的中央访问点。如果在某个时候管理应用程序需要更改服务器分配(例如,将其从允许写改为仅允许读),则它将更改服务器的版本令牌列表并更新其缓存。

.为了提高性能,客户端应用程序从管理应用程序获取缓存信息,使它们不必为每个语句检索关于服务器分配的信息。基于它将发出的语句类型(例如,读与写),客户端选择适当的服务器并连接到它

.此外,客户端向服务器发送自己的客户端特定版本的令牌来注册它需要的服务器分配。对于客户端发送到服务器的每个语句,服务器将自己的令牌列表与客户端令牌列表进行比较。如果服务器令牌列表包含客户端令牌列表中所有具有相同值的令牌,则存在匹配,服务器执行该语句

另一方面,可能管理应用程序更改了服务器分配及其版本令牌列表。在这种情况下,新的服务器分配现在可能与客户端需求不兼容。服务器和客户端令牌列表之间的令牌不匹配,服务器返回一个错误作为对语句的应答。这指示客户机从管理应用程序缓存中刷新其版本令牌信息,并选择要与之通信的新服务器。

检测版本令牌错误和选择新服务器的客户端逻辑可以通过不同的方式实现:
.客户端可以自己处理所有版本令牌注册、不匹配检测和连接切换
.这些操作的逻辑可以在管理客户端和MySQL服务器之间连接的连接器中实现。这样的连接器可以处理错配错误检测和语句重新发送本身,也可以将错误传递给应用程序,并将其留给应用程序重新发送语句。

下面的例子以更具体的形式说明了前面的讨论。
当版本令牌在给定服务器上初始化时,服务器的版本令牌列表为空。通过调用用户定义函数(udf)来执行令牌列表维护。调用任何版本令牌udf都需要超级特权,因此具有该特权的管理或管理应用程序需要修改令牌列表。

假设一个管理应用程序与一组服务器通信,客户端查询这些服务器以访问雇员和产品数据库(分别名为emp和prod)。所有服务器都被允许处理数据检索语句,但只有一部分服务器被允许进行数据库更新。为了在特定于数据库的基础上处理这个问题,管理应用程序在每个服务器上建立一个版本令牌列表。在给定服务器的令牌列表中,令牌名称表示数据库名称,读写令牌值取决于数据库是否必须以只读方式使用,或者是否可以进行读写。

客户端应用程序通过设置系统变量来注册它们需要服务器匹配的版本令牌列表。变量设置是在客户端特定的基础上进行的,因此不同的客户端可以注册不同的需求。默认情况下,客户端令牌列表是空的,它匹配任何服务器令牌列表。当客户端将其令牌列表设置为非空值时,匹配可能成功也可能失败,这取决于服务器版本令牌列表。

为了定义服务器的版本令牌列表,管理应用程序调用version_token_set() UDF。(稍后将介绍用于修改和显示令牌列表的udf。)例如,应用程序可能将这些语句发送到三个服务器组成的组
服务器1:

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

服务器2:

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

服务器3:

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

在每种情况下,令牌列表都被指定为以分号分隔的名称=值对列表。产生的令牌列表值导致这些服务器连接:
.任何服务器都会接受对两个数据库中的任意一个进行读取
.只有服务器2接受对emp数据库的更新
.只有服务器3接受对prod数据库的更新

除了为每个服务器分配一个版本令牌列表外,管理应用程序还维护一个反映服务器分配的缓存。

在与服务器通信之前,客户机应用程序与管理应用程序进行联系,并检索关于服务器分配的信息。然后客户端根据这些分配选择服务器。假设客户机希望同时执行对emp数据库的读写操作。根据前面的分配,只有服务器2合格。客户机连接到服务器2,并通过设置
version_tokens_session系统变量在服务器2上注册服务器需求:

mysql> SET @@session.version_tokens_session = 'emp=write';
Query OK, 0 rows affected (0.00 sec)

对于客户机发送到服务器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值中的令牌名称在服务器令牌列表中不存在。在这种情况下会发生ER_VTOKEN_PLUGIN_TOKEN_NOT_FOUND错误
.version_tokens_session值中的令牌值与服务器令牌列表中相应令牌的值不同。在这种情况下将出现ER_VTOKEN_PLUGIN_TOKEN_MISMATCH错误

只要服务器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.        |
+----------------------------------+
1 row in set (0.00 sec)

服务器2:

mysql> SELECT version_tokens_edit('emp=read');
+---------------------------------+
| version_tokens_edit('emp=read') |
+---------------------------------+
| 1 version tokens updated.       |
+---------------------------------+
1 row in set (0.00 sec)

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值)中命名的每个令牌获取一个共享锁
.执行服务器和客户端令牌列表之间的比较
.根据比较结果执行语句或产生错误
.释放锁

服务器使用共享锁,以便可以在不阻塞的情况下对多个会话进行比较,同时防止对任何试图在操作服务器令牌列表中具有相同名称的令牌之前获取独占锁的会话的令牌进行更改

前面的例子只使用了版本标记插件库中包含的一些用户定义,但是还有其他的。一组udf允许对服务器的版本令牌列表进行操作和检查。另一组udf允许锁定和解锁版本标记

这些udf允许创建、更改、删除和检查服务器的版本标记列表:
.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.               |
+-------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT version_tokens_edit('tok3=c');
+-------------------------------+
| version_tokens_edit('tok3=c') |
+-------------------------------+
| 1 version tokens updated.     |
+-------------------------------+
1 row in set (0.00 sec)

mysql> SELECT version_tokens_delete('tok2;tok1');
+------------------------------------+
| version_tokens_delete('tok2;tok1') |
+------------------------------------+
| 2 version tokens deleted.          |
+------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT version_tokens_show();
+-----------------------+
| version_tokens_show() |
+-----------------------+
| tok3=c;               |
+-----------------------+
1 row in set (0.00 sec)

如果令牌列表格式不正确,就会出现警告:

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.                                         |
+---------------------------------------------------------------+
1 row in set (0.00 sec)

版本标记对参数的解释如下:
.名称和值周围的空白将被忽略。允许在名称和值中使用空格。(对于version_tokens_delete(),它接受一个没有值的名称列表,名称周围的空白将被忽略。)
.没有报价机制
.令牌的顺序并不重要,除非令牌列表包含给定令牌名称的多个实例,否则最后一个值优先于前面的值

根据这些规则,前面的version_tokens_set()调用会产生一个令牌列表,其中包含两个令牌:tok1的值是1’2 3’4,tok2的值是a = b。

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

如果令牌列表包含两个令牌,为什么version_tokens_set()返回设置的值3版本令牌?这是因为原来的令牌列表包含两个tok1定义,而第二个定义替换了第一个定义。

版本标记令牌操作udf将这些约束放在令牌名称和值上:
.令牌名称不能包含=或;字符,最大长度为64个字符
.令牌值不能包含;字符。值的长度受到max_allowed_packet系统变量的值的限制
.版本令牌将令牌名称和值视为二进制字符串,因此比较是区分大小写的

版本令牌还包括一组udf,允许对令牌进行锁定和解锁:
.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)'.

使用版本标记锁定功能的锁定是建议的;申请必须同意合作。

可以锁定不存在的令牌名称。这不会创建令牌。

对于版本令牌锁定函数,令牌名称参数完全按照指定的方式使用。周围的空白不被忽略,并且=和;字符是允许的。这是因为令牌只是像传递
给锁定服务一样传递要锁定的令牌名称。

版本标记引用

版本标记功能
版本令牌插件库包含几个用户定义的函数。一组udf允许对服务器的版本令牌列表进行操作和检查。另一组udf允许锁定和解锁版本标记。调用任何版本令牌UDF都需要超级特权。

下面的udf允许创建、更改、删除和检查服务器的版本令牌列表:
.version_tokens_delete (name_list)
使用name_list参数从服务器的版本令牌列表中删除令牌,并返回指示操作结果的二进制字符串。name_list是要删除的版本令牌名称的分号分隔列表。

mysql> SELECT version_tokens_delete('tok1;tok3');
+------------------------------------+
| version_tokens_delete('tok1;tok3') |
+------------------------------------+
| 2 version tokens deleted.          |
+------------------------------------+
1 row in set (0.00 sec)

从MySQL 5.7.9开始,NULL参数被视为空字符串,这对令牌列表没有影响。
version_tokens_delete()删除其参数中指定的标记(如果它们存在的话)。(删除不存在的令牌不是错误。)要在不知道列表中有哪些令牌的情况下完全清除令牌列表,请将NULL或不包含令牌的字符串传递给version_tokens_set():

mysql> SELECT version_tokens_set(NULL);
+------------------------------+
| version_tokens_set(NULL)     |
+------------------------------+
| Version tokens list cleared. |
+------------------------------+
1 row in set (0.00 sec)

mysql> SELECT version_tokens_set('');
+------------------------------+
| version_tokens_set('')       |
+------------------------------+
| Version tokens list cleared. |
+------------------------------+
1 row in set (0.00 sec)

.version_tokens_edit (token_list)
使用token_list参数修改服务器的版本令牌列表,并返回指示操作结果的二进制字符串。token_list是一个以分号分隔的名称=值对列表,它指定要定义的每个令牌的名称及其值。如果存在令牌,则使用给定的值更新其值。如果标记不存在,则使用给定的值创建它。如果参数为NULL或字符串不包含令牌,则令牌列表保持不变。

mysql> SELECT version_tokens_set('tok1=value1;tok2=value2');
+-----------------------------------------------+
| version_tokens_set('tok1=value1;tok2=value2') |
+-----------------------------------------------+
| 2 version tokens set.                         |
+-----------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT version_tokens_edit('tok2=new_value2;tok3=new_value3');
+--------------------------------------------------------+
| version_tokens_edit('tok2=new_value2;tok3=new_value3') |
+--------------------------------------------------------+
| 2 version tokens updated.                              |
+--------------------------------------------------------+
1 row in set (0.00 sec)

.version_tokens_set (token_list)
用token_list参数中定义的令牌替换服务器的版本令牌列表,并返回指示操作结果的二进制字符串。token_list是一个用分号分隔的名称=值对列表,指定要定义的每个令牌的名称及其值。如果参数为空或字符串不包含令牌,则清除令牌列表。

mysql> SELECT version_tokens_set('tok1=value1;tok2=value2');
+-----------------------------------------------+
| version_tokens_set('tok1=value1;tok2=value2') |
+-----------------------------------------------+
| 2 version tokens set.                         |
+-----------------------------------------------+
1 row in set (0.00 sec)

.version_tokens_show()
以二进制字符串的形式返回服务器的版本标记列表,其中包含一个以分号分隔的名称=值对列表。

mysql> SELECT version_tokens_show();
+--------------------------+
| version_tokens_show()    |
+--------------------------+
| tok2=value2;tok1=value1; |
+--------------------------+
1 row in set (0.00 sec)

下面的udf允许锁定和解锁版本标记:
.version_tokens_lock_exclusive (token_name [token_name]…超时)
获取一个或多个版本令牌(按名称指定为字符串)上的独占锁,如果未在给定的超时值内获取锁,则超时并报错

mysql> SELECT version_tokens_lock_exclusive('lock1', 'lock2', 10);
+-----------------------------------------------------+
| version_tokens_lock_exclusive('lock1', 'lock2', 10) |
+-----------------------------------------------------+
| 1 |
+-----------------------------------------------------+

这个函数是在MySQL 5.7.8中添加的,名为vtoken_get_write_locks(),在5.7.9中重命名为version_tokens_lock_exclusive()

.version_tokens_lock_shared (token_name [token_name]…超时)
获取一个或多个版本令牌(按名称指定为字符串)上的共享锁,如果未在给定的超时值内获取锁,则超时并报错

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

这个函数是在MySQL 5.7.8中添加的,名为vtoken_get_read_locks(),在5.7.9中重命名为version_tokens_lock_shared()

.version_tokens_unlock ()
使用version_tokens_lock_exclusive()和version_tokens_lock_shared()释放在当前会话中获取的所有锁。

mysql> SELECT version_tokens_unlock();
+-------------------------+
| version_tokens_unlock() |
+-------------------------+
| 1 |
+-------------------------+

这个函数是在MySQL 5.7.8中添加的,名为vtoken_release_locks(),在5.7.9中重命名为version_tokens_unlock()。

锁定功能共享这些特性:
.对于成功,返回值为非零。否则,将发生错误
.令牌名称是字符串
.与操作服务器令牌列表的udf的参数处理不同,令牌名称参数周围的空白不会被忽略,并且=和;字符是允许的
.可以锁定不存在的令牌名称。这不会创建令牌
.超时值是非负整数,表示在出现错误超时之前等待获取锁所需的时间(以秒为单位)。如果超时为0,则不存在等待,如果不能立即获取锁,则该函数将产生一个错误
.版本令牌锁定功能基于所描述的锁定服务在Section 28.3.1 锁服务中描述。

版本令牌系统变量
版本标记支持以下系统变量。这些变量不可用,除非安装版本令牌插件

系统变量:
.version_tokens_session
命令行格式:–version-tokens-session=value
变量范围:Global,Session
动态:Yes
允许的值:类型为字符串,默认值为NULL
此变量的会话值指定客户端版本令牌列表,并指示客户端会话要求服务器版本令牌列表具有的令牌。

如果version_tokens_session变量为NULL(默认值)或值为空,则任何服务器版本令牌列表都是匹配的。(实际上,空值会禁用匹配需求。)

如果version_tokens_session变量有一个非空值,那么它的值与服务器版本令牌列表之间的任何不匹配都会导致会话发送给服务器的任何语句出错。在这种情况下会发生失配:
.version_tokens_session值中的令牌名称在服务器令牌列表中不存在。在本例中,发生了ER_VTOKEN_PLUGIN_TOKEN_NOT_FOUND错误
.version_tokens_session值中的令牌值与服务器令牌列表中相应令牌的值不同。在本例中,将出现ER_VTOKEN_PLUGIN_TOKEN_MISMATCH错误

服务器版本令牌列表中包含没有在version_tokens_session值中命名的令牌不是不匹配的

假设一个管理应用程序将服务器令牌列表设置为如下所示:

mysql> SELECT version_tokens_set('tok1=a;tok2=b;tok3=c');
+--------------------------------------------+
| version_tokens_set('tok1=a;tok2=b;tok3=c') |
+--------------------------------------------+
| 3 version tokens set. |
+--------------------------------------------+

客户端通过设置其version_tokens_session值来注册它需要服务器匹配的令牌。然后,对于客户端发送的每个后续语句,服务器将根据客户
端version_tokens_session值检查其令牌列表,如果存在不匹配,则产生一个错误:

mysql> SET @@session.version_tokens_session = 'tok1=a;tok2=b';
mysql> SELECT 1;
+---+
| 1 |
+---+
| 1 |
+---+
mysql> SET @@session.version_tokens_session = 'tok1=b';
mysql> SELECT 1;
ERROR 3136 (42000): Version token mismatch for tok1. Correct value a

第一个选择成功是因为客户端令牌tok1和tok2出现在服务器令牌列表中,并且每个令牌在服务器列表中具有相同的值。第二个SELECT失败是因为,虽然tok1出现在服务器令牌列表中,但它的值与客户机指定的值不同

此时,客户端发送的任何语句都将失败,除非服务器令牌列表发生更改,使其再次匹配。假设管理应用程序按如下方式更改服务器令牌列表:

mysql> SELECT version_tokens_edit('tok1=b');
+-------------------------------+
| version_tokens_edit('tok1=b') |
+-------------------------------+
| 1 version tokens updated. |
+-------------------------------+
mysql> SELECT version_tokens_show();
+-----------------------+
| version_tokens_show() |
+-----------------------+
| tok3=c;tok1=b;tok2=b; |
+-----------------------+

现在,客户机version_tokens_session值与服务器令牌列表匹配,客户机可以再次成功执行语句:

mysql> SELECT 1;
+---+
| 1 |
+---+
| 1 |
+---+

这个变量是在MySQL 5.7.8中添加的
.version_tokens_session_number
命令行格式:–version-tokens-session-number=N
变量范围:Global,Session
动态:NO
允许的值:类型为整型,默认值为0
此变量供内部使用。
这个变量是在MySQL 5.7.8中添加的。

One thought on “MySQL Version Tokens

发表评论

电子邮件地址不会被公开。