MySQL8 中文参考(二十二)

2024-06-26 19:12:01 浏览数 (1)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

原文:dev.mysql.com/doc/refman/8.0/en/ddl-rewriter-installation.html

7.6.5.1 安装或卸载 ddl_rewriter

本节描述了如何安装或卸载ddl_rewriter插件。有关安装插件的一般信息,请参见 Section 7.6.1,“安装和卸载插件”。

注意

如果安装了ddl_rewriter插件,即使禁用了,也会涉及一些最小的开销。为避免这种开销,只在打算使用它的期间安装ddl_rewriter

主要用例是修改从转储文件中恢复的语句,因此典型的使用模式是:1)安装插件;2)恢复转储文件或文件;3)卸载插件。

要被服务器使用,插件库文件必须位于 MySQL 插件目录中(由plugin_dir系统变量命名的目录)。如有必要,在服务器启动时通过设置plugin_dir的值来配置插件目录位置。

插件库文件基本名称为ddl_rewriter。文件名后缀因平台而异(例如,Unix 和类 Unix 系统为.so,Windows 为.dll)。

要安装ddl_rewriter插件,请使用INSTALL PLUGIN语句,根据需要调整您平台的.so后缀:

代码语言:javascript复制
INSTALL PLUGIN ddl_rewriter SONAME 'ddl_rewriter.so';

要验证插件安装,请检查信息模式PLUGINS表或使用SHOW PLUGINS语句(参见 Section 7.6.2,“获取服务器插件信息”)。例如:

代码语言:javascript复制
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS, PLUGIN_TYPE
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE 'ddl%';
 -------------- --------------- ------------- 
| PLUGIN_NAME  | PLUGIN_STATUS | PLUGIN_TYPE |
 -------------- --------------- ------------- 
| ddl_rewriter | ACTIVE        | AUDIT       |
 -------------- --------------- ------------- 

如前述结果所示,ddl_rewriter被实现为审计插件。

如果插件初始化失败,请检查服务器错误日志以获取诊断消息。

一旦按照上述描述安装,ddl_rewriter将保持安装状态,直到卸载。要删除它,请使用UNINSTALL PLUGIN

代码语言:javascript复制
UNINSTALL PLUGIN ddl_rewriter;

如果安装了ddl_rewriter,您可以使用--ddl-rewriter选项来控制后续服务器启动时ddl_rewriter插件的激活。例如,要防止插件在运行时启用,请使用此选项:

代码语言:javascript复制
[mysqld]
ddl-rewriter=OFF

原文:dev.mysql.com/doc/refman/8.0/en/ddl-rewriter-options.html

7.6.5.2 ddl_rewriter 插件选项

本节描述了控制ddl_rewriter插件操作的命令选项。如果在启动时指定的值不正确,则ddl_rewriter插件可能无法正确初始化,服务器也不会加载它。

要控制ddl_rewriter插件的激活,请使用此选项:

  • --ddl-rewriter[=*value*] 命令行格式--ddl-rewriter[=value]引入版本8.0.16类型枚举默认值ON有效值ON``OFF``FORCE``FORCE_PLUS_PERMANENT此选项控制服务器在启动时如何加载ddl_rewriter插件。仅当插件先前已通过INSTALL PLUGIN注册或通过--plugin-load--plugin-load-add加载时才可用。参见 Section 7.6.5.1, “Installing or Uninstalling ddl_rewriter”。 选项值应为插件加载选项中可用的值之一,如 Section 7.6.1, “Installing and Uninstalling Plugins”中所述。例如,--ddl-rewriter=OFF可在服务器启动时禁用插件。

7.6.6 版本标记

原文:dev.mysql.com/doc/refman/8.0/en/version-tokens.html

7.6.6.1 版本标记元素

7.6.6.2 安装或卸载版本标记

7.6.6.3 使用版本标记

7.6.6.4 版本标记参考

MySQL 包括版本标记,这是一个功能,可以创建和围绕服务器标记进行同步,应用程序可以使用这些标记来防止访问不正确或过时的数据。

版本标记接口具有以下特征:

  • 版本标记是由一个作为键或标识符的名称和一个值组成的对。
  • 版本标记可以被锁定。应用程序可以使用标记锁定来指示其他合作应用程序正在使用标记,不应该被修改。
  • 版本标记列表是针对每个服务器建立的(例如,用于指定服务器分配或操作状态)。此外,与服务器通信的应用程序可以注册其自己的标记列表,指示其需要服务器处于的状态。应用程序向未处于所需状态的服务器发送的 SQL 语句会产生错误。这是一个信号,告诉应用程序应该寻找一个处于所需状态的不同服务器来接收 SQL 语句。

以下各节描述了版本标记的元素,讨论了如何安装和使用它,并为其元素提供了参考信息。

原文:dev.mysql.com/doc/refman/8.0/en/version-tokens-elements.html

7.6.6.1 版本令牌元素

版本令牌基于一个实现以下元素的插件库:

  • 一个名为version_tokens的服务器端插件保存与服务器关联的版本令牌列表,并订阅语句执行事件的通知。version_tokens插件使用审计插件 API 来监视来自客户端的传入语句,并将每个客户端的会话特定版本令牌列表与服务器版本令牌列表进行匹配。如果匹配成功,插件允许语句通过,服务器继续处理。否则,插件向客户端返回错误,语句失败。
  • 一组可加载函数提供了一个 SQL 级 API,用于操作和检查插件维护的服务器版本令牌列表。调用任何版本令牌函数都需要VERSION_TOKEN_ADMIN权限(或已弃用的SUPER权限)。
  • version_tokens插件加载时,它定义了VERSION_TOKEN_ADMIN动态权限。这个权限可以授予函数的用户。
  • 一个系统变量使客户端能够指定注册所需服务器状态的版本令牌列表。如果服务器在客户端发送语句时处于不同状态,则客户端会收到错误。

原文:dev.mysql.com/doc/refman/8.0/en/version-tokens-installation.html

7.6.6.2 安装或卸载版本标记

注意

如果安装了版本标记,会涉及一些开销。为避免这种开销,请不要安装它,除非您打算使用它。

本节描述了如何安装或卸载版本标记(Version Tokens),它是在一个包含插件和可加载函数的插件库文件中实现的。有关安装或卸载插件和可加载函数的一般信息,请参见第 7.6.1 节,“安装和卸载插件”,以及第 7.7.1 节,“安装和卸载可加载函数”。

要使服务器可用,插件库文件必须位于 MySQL 插件目录中(由plugin_dir系统变量命名的目录)。如有必要,在服务器启动时通过设置plugin_dir的值来配置插件目录位置。

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

要安装版本标记插件和函数,请使用INSTALL PLUGINCREATE FUNCTION语句,根据需要调整平台的.so后缀:

代码语言:javascript复制
INSTALL PLUGIN version_tokens SONAME 'version_token.so';
CREATE FUNCTION version_tokens_set RETURNS STRING
  SONAME 'version_token.so';
CREATE FUNCTION version_tokens_show RETURNS STRING
  SONAME 'version_token.so';
CREATE FUNCTION version_tokens_edit RETURNS STRING
  SONAME 'version_token.so';
CREATE FUNCTION version_tokens_delete RETURNS STRING
  SONAME 'version_token.so';
CREATE FUNCTION version_tokens_lock_shared RETURNS INT
  SONAME 'version_token.so';
CREATE FUNCTION version_tokens_lock_exclusive RETURNS INT
  SONAME 'version_token.so';
CREATE FUNCTION version_tokens_unlock RETURNS INT
  SONAME 'version_token.so';

您必须安装用于管理服务器版本标记列表的函数,但也必须安装插件,因为没有插件,函数无法正常工作。

如果插件和函数在复制源服务器上使用,请在所有副本服务器上安装它们,以避免复制问题。

一旦按照上述方式安装,插件和函数将保持安装状态直到卸载。要移除它们,请使用UNINSTALL PLUGINDROP FUNCTION语句:

代码语言:javascript复制
UNINSTALL PLUGIN version_tokens;
DROP FUNCTION version_tokens_set;
DROP FUNCTION version_tokens_show;
DROP FUNCTION version_tokens_edit;
DROP FUNCTION version_tokens_delete;
DROP FUNCTION version_tokens_lock_shared;
DROP FUNCTION version_tokens_lock_exclusive;
DROP FUNCTION version_tokens_unlock;

原文:dev.mysql.com/doc/refman/8.0/en/version-tokens-usage.html

7.6.6.3 使用版本令牌

在使用版本令牌之前,请根据第 7.6.6.2 节,“安装或卸载版本令牌”中提供的说明进行安装。

版本令牌可以派上用场的一个场景是访问一组 MySQL 服务器的系统,但需要通过监视它们并根据负载变化调整服务器分配来进行负载平衡管理。这样的系统包括以下元素:

  • 要管理的 MySQL 服务器集合。
  • 与服务器通信并将其组织成高可用性组的管理或管理应用程序。组具有不同的目的,每个组内的服务器可能具有不同的分配。某个组内服务器的分配可以随时更改。
  • 客户端应用程序访问服务器以检索和更新数据,根据分配给它们的目的选择服务器。例如,客户端不应向只读服务器发送更新。

版本令牌允许根据分配管理服务器访问,而无需客户端反复查询服务器的分配情况:

  • 管理应用程序执行服务器分配并在每个服务器上建立版本令牌以反映其分配。该应用程序缓存此信息以提供对其的集中访问点。 如果管理应用程序在某个时刻需要更改服务器分配(例如,将其从允许写入更改为只读),则更改服务器的版本令牌列表并更新其缓存。
  • 为了提高性能,客户端应用程序从管理应用程序获取缓存信息,使它们无需为每个语句检索有关服务器分配的信息。根据其发出的语句类型(例如,读取与写入),客户端选择适当的服务器并连接到它。
  • 此外,客户端向服务器发送自己的客户端特定版本令牌,以注册其对服务器所需的分配。对于客户端发送给服务器的每个语句,服务器将其自己的令牌列表与客户端令牌列表进行比较。如果服务器令牌列表包含客户端令牌列表中具有相同值的所有令牌,则存在匹配项,服务器执行该语句。 另一方面,也许管理应用程序已更改了服务器分配及其版本令牌列表。在这种情况下,新的服务器分配现在可能与客户端要求不兼容。服务器和客户端令牌列表之间存在令牌不匹配,并且服务器在回复语句中返回错误。这是向客户端指示从管理应用程序缓存中刷新其版本令牌信息,并选择一个新服务器进行通信的迹象。

用于检测版本令牌错误并选择新服务器的客户端端逻辑可以以不同的方式实现:

  • 客户端可以自行处理所有版本令牌注册、不匹配检测和连接切换。
  • 这些操作的逻辑可以在一个连接器中实现,该连接器管理客户端和 MySQL 服务器之间的连接。这样的连接器可能会自行处理不匹配错误检测和语句重发,或者将错误传递给应用程序,由应用程序重新发送语句。

以下示例以更具体的形式说明了前面的讨论。

当版本令牌在给定服务器上初始化时,服务器的版本令牌列表为空。通过调用函数执行令牌列表维护。调用任何版本令牌函数都需要VERSION_TOKEN_ADMIN权限(或已弃用的SUPER权限),因此预计令牌列表修改将由具有该权限的管理或管理应用程序执行。

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

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

要为服务器定义版本令牌列表,管理应用程序调用version_tokens_set()函数。(还有用于修改和显示令牌列表的函数,稍后描述。)例如,应用程序可能向三个服务器组发送以下语句:

服务器 1:

代码语言:javascript复制
mysql> SELECT version_tokens_set('emp=read;prod=read');
 ------------------------------------------ 
| version_tokens_set('emp=read;prod=read') |
 ------------------------------------------ 
| 2 version tokens set.                    |
 ------------------------------------------ 

服务器 2:

代码语言:javascript复制
mysql> SELECT version_tokens_set('emp=write;prod=read');
 ------------------------------------------- 
| version_tokens_set('emp=write;prod=read') |
 ------------------------------------------- 
| 2 version tokens set.                     |
 ------------------------------------------- 

服务器 3:

代码语言:javascript复制
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系统变量在那里注册其服务器要求:

代码语言:javascript复制
mysql> SET @@SESSION.version_tokens_session = 'emp=write';

对于客户端发送到服务器 2 的后续语句,服务器将比较自己的版本令牌列表与客户端列表,以检查它们是否匹配。如果匹配,则语句正常执行:

代码语言:javascript复制
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:

代码语言:javascript复制
mysql> SELECT version_tokens_edit('emp=write');
 ---------------------------------- 
| version_tokens_edit('emp=write') |
 ---------------------------------- 
| 1 version tokens updated.        |
 ---------------------------------- 

服务器 2:

代码语言:javascript复制
mysql> SELECT version_tokens_edit('emp=read');
 --------------------------------- 
| version_tokens_edit('emp=read') |
 --------------------------------- 
| 1 version tokens updated.       |
 --------------------------------- 

version_tokens_edit() 修改服务器令牌列表中命名的令牌,并保持其他令牌不变。

下次客户端向服务器 2 发送语句时,其自身的令牌列表不再与服务器令牌列表匹配,将会发生错误:

代码语言:javascript复制
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_set() 完全替换当前列表并分配新列表。参数是一个以分号分隔的*name*=*value*对列表。
  • version_tokens_edit() 允许对当前列表进行部分修改。它可以添加新令牌或更改现有令牌的值。参数是一个以分号分隔的*name*=*value*对列表。
  • version_tokens_delete() 从当前列表中删除令牌。参数是一个以分号分隔的令牌名称列表。
  • version_tokens_show() 显示当前令牌列表。它不需要参数。

如果成功,这些函数中的每一个都会返回一个指示发生了什么操作的二进制字符串。以下示例建立了服务器令牌列表,通过添加新令牌对其进行修改,删除一些令牌,并显示生成的令牌列表:

代码语言:javascript复制
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;               |
 ----------------------- 

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

代码语言:javascript复制
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 WARNINGSG
*************************** 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()的调用:

代码语言:javascript复制
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_delete(),它接受没有值的名称列表,名称周围的空格将被忽略。)
  • 没有引用机制。
  • 令牌的顺序不重要,除非令牌列表包含给定令牌名称的多个实例,最后一个值优先于先前的值。

根据这些规则,前面的version_tokens_set()调用会导致一个包含两个令牌的令牌列表:tok1的值为1'2 3"4tok2的值为a = b。要验证这一点,请调用version_tokens_show()

代码语言:javascript复制
mysql> SELECT version_tokens_show();
 -------------------------- 
| version_tokens_show()    |
 -------------------------- 
| tok2=a = b;tok1=1'2 3"4; |
 -------------------------- 

如果令牌列表包含两个令牌,为什么version_tokens_set()返回值为3 version tokens set?这是因为原始令牌列表包含了两个tok1的定义,第二个定义替换了第一个。

版本令牌的令牌操作函数对令牌名称和值施加了以下约束:

  • 令牌名称不能包含=��字符,最大长度为 64 个字符。
  • 令牌值不能包含字符。值的长度受max_allowed_packet系统变量值的限制。
  • 版本令牌将令牌名称和值视为二进制字符串,因此比较区分大小写。

版本令牌还包括一组函数,使令牌可以被锁定和解锁:

  • version_tokens_lock_exclusive()获取独占版本令牌锁。它接受一个或多个锁名称列表和一个超时值。
  • version_tokens_lock_shared()获取共享版本令牌锁。它接受一个或多个锁名称列表和一个超时值。
  • version_tokens_unlock()释放版本令牌锁(独占和共享)。它不接受参数。

每个锁定函数返回非零值表示成功。否则,将发生错误:

代码语言:javascript复制
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)'.

使用版本令牌锁定函数进行锁定是建议性的;应用程序必须同意合作。

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

注意

版本令牌锁定函数基于第 7.6.9.1 节,“锁定服务”中描述的锁定服务,并且对于共享和独占锁具有相同的语义。(版本令牌使用内置于服务器中的锁定服务例程,而不是锁定服务函数接口,因此不需要安装这些函数来使用版本令牌。)版本令牌获取的锁使用 version_token_locks 的锁定服务命名空间。可以使用性能模式监视锁定服务锁,因此对于版本令牌锁也是如此。有关详细信息,请参见锁定服务监控。

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

原文:dev.mysql.com/doc/refman/8.0/en/version-tokens-reference.html

7.6.6.4 版本标记参考

以下讨论作为这些版本标记元素的参考:

  • 版本标记函数
  • 版本标记系统变量
版本标记函数

版本标记插件库包含多个函数。一组函数允许操作和检查服务器的版本标记列表。另一组函数允许锁定和解锁版本标记。调用任何版本标记函数都需要VERSION_TOKEN_ADMIN权限(或已弃用的SUPER权限)。

以下函数允许创建、更改、删除和检查服务器的版本标记列表。对*name_listtoken_list*参数的解释(包括空格处理)如第 7.6.6.3 节“使用版本标记”所述,该节提供了关于指定标记语法的详细信息,以及额外的示例。

version_tokens_delete(*name_list*)

使用*name_list参数从服务器的版本标记列表中删除标记,并返回指示操作结果的二进制字符串。name_list*是一个以分号分隔的版本标记名称列表,用于删除。

代码语言:javascript复制
mysql> SELECT version_tokens_delete('tok1;tok3');
 ------------------------------------ 
| version_tokens_delete('tok1;tok3') |
 ------------------------------------ 
| 2 version tokens deleted.          |
 ------------------------------------ 

NULL参数被视为空字符串,对标记列表没有影响。

version_tokens_delete() 删除其参数中命名的标记(如果存在)。(删除不存在的标记不会报错。)要清除标记列表而不知道列表中有哪些标记,可以传递NULL或一个不包含任何标记的字符串给version_tokens_set()

代码语言:javascript复制
mysql> SELECT version_tokens_set(NULL);
 ------------------------------ 
| version_tokens_set(NULL)     |
 ------------------------------ 
| Version tokens list cleared. |
 ------------------------------ 
mysql> SELECT version_tokens_set('');
 ------------------------------ 
| version_tokens_set('')       |
 ------------------------------ 
| Version tokens list cleared. |
 ------------------------------ 

version_tokens_edit(*token_list*)

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

代码语言:javascript复制
mysql> SELECT version_tokens_set('tok1=value1;tok2=value2');
 ----------------------------------------------- 
| version_tokens_set('tok1=value1;tok2=value2') |
 ----------------------------------------------- 
| 2 version tokens set.                         |
 ----------------------------------------------- 
mysql> SELECT version_tokens_edit('tok2=new_value2;tok3=new_value3');
 -------------------------------------------------------- 
| version_tokens_edit('tok2=new_value2;tok3=new_value3') |
 -------------------------------------------------------- 
| 2 version tokens updated.                              |
 -------------------------------------------------------- 

version_tokens_set(*token_list*)

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

代码语言:javascript复制
mysql> SELECT version_tokens_set('tok1=value1;tok2=value2');
 ----------------------------------------------- 
| version_tokens_set('tok1=value1;tok2=value2') |
 ----------------------------------------------- 
| 2 version tokens set.                         |
 ----------------------------------------------- 

version_tokens_show()

将服务器的版本令牌列表作为包含以分号分隔的*name*=*value*对列表的二进制字符串返回。

代码语言:javascript复制
mysql> SELECT version_tokens_show();
 -------------------------- 
| version_tokens_show()    |
 -------------------------- 
| tok2=value2;tok1=value1; |
 -------------------------- 

以下函数允许锁定和解锁版本令牌:

version_tokens_lock_exclusive(*token_name*[, *token_name*] ..., *timeout*)

获取由名称指定为字符串的一个或多个版本令牌的独占锁,在给定的超时值内超时并出现错误,如果在给定的超时值内未获得锁。

代码语言:javascript复制
mysql> SELECT version_tokens_lock_exclusive('lock1', 'lock2', 10);
 ----------------------------------------------------- 
| version_tokens_lock_exclusive('lock1', 'lock2', 10) |
 ----------------------------------------------------- 
|                                                   1 |
 ----------------------------------------------------- 

version_tokens_lock_shared(*token_name*[, *token_name*] ..., *timeout*)

获取由名称指定为字符串的一个或多个版本令牌的共享锁,在给定的超时值内超时并出现错误,如果在给定的超时值内未获得锁。

代码语言:javascript复制
mysql> SELECT version_tokens_lock_shared('lock1', 'lock2', 10);
 -------------------------------------------------- 
| version_tokens_lock_shared('lock1', 'lock2', 10) |
 -------------------------------------------------- 
|                                                1 |
 -------------------------------------------------- 

version_tokens_unlock()

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

代码语言:javascript复制
mysql> SELECT version_tokens_unlock();
 ------------------------- 
| version_tokens_unlock() |
 ------------------------- 
|                       1 |
 ------------------------- 

锁定函数具有以下特征:

  • 返回值为非零表示成功。否则,将发生错误。
  • 令牌名称为字符串。
  • 与操作服务器令牌列表的函数的参数处理相反,不会忽略围绕令牌名称参数的空白,并且允许使用=;字符。
  • 可以锁定不存在的令牌名称。这不会创建令牌。
  • 超时值是表示在超时前等待获取锁的时间(以秒为单位)的非负整数。如果超时为 0,则不会等待,如果无法立即获取锁,则函数会产生错误。
  • 版本令牌锁定函数基于第 7.6.9.1 节,“锁定服务”中描述的锁定服务。
版本令牌系统变量

版本令牌支持以下系统变量。除非安装了版本令牌插件(请参阅第 7.6.6.2 节,“安装或卸载版本令牌”),否则这些变量不可用。

系统变量:

version_tokens_session

命令行格式

--version-tokens-session=value

系统变量

version_tokens_session

范围

全局,会话

动态

SET_VAR提示适用

类型

字符串

默认值

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值中命名的令牌并不构成不匹配。

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

代码语言:javascript复制
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值进行比较,如果不匹配则产生错误:

代码语言:javascript复制
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

第一个SELECT成功,因为客户端令牌tok1tok2存在于服务器令牌列表中,并且每个令牌在服务器列表中具有相同的值。第二个SELECT失败,因为虽然tok1存在于服务器令牌列表中,但其值与客户端指定的值不同。

此时,除非服务器令牌列表发生变化以匹配,否则客户端发送的任何语句都会失败。假设管理应用程序将服务器令牌列表更改如下:

代码语言:javascript复制
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值与服务器令牌列表匹配,客户端可以再次成功执行语句:

代码语言:javascript复制
mysql> SELECT 1;
 --- 
| 1 |
 --- 
| 1 |
 --- 

version_tokens_session_number

命令行格式

--version-tokens-session-number=#

系统变量

version_tokens_session_number

范围

全局,会话

动态

SET_VAR提示适用

类型

整数

默认值

0

此变量仅供内部使用。

7.6.7 克隆插件

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin.html

7.6.7.1 安装克隆插件

7.6.7.2 本地克隆数据

7.6.7.3 克隆远程数据

7.6.7.4 克隆和并发 DDL

7.6.7.5 克隆加密数据

7.6.7.6 克隆压缩数据

7.6.7.7 用于复制的克隆

7.6.7.8 克隆操作期间创建的目录和文件

7.6.7.9 处理远程克隆操作失败

7.6.7.10 监控克隆操作

7.6.7.11 停止克隆操作

7.6.7.12 克隆系统变量参考

7.6.7.13 克隆系统变量

7.6.7.14 克隆插件限制

克隆插件,引入于 MySQL 8.0.17,允许在本地或从远程 MySQL 服务器实例克隆数据。克隆数据是存储在 InnoDB 中的数据的物理快照,包括模式、表、表空间和数据字典元数据。克隆数据包括一个完全功能的数据目录,允许使用克隆插件进行 MySQL 服务器的配置。

图 7.1 本地克隆操作

CLONE LOCAL 语句将本地 MySQL 服务器实例上的数据目录克隆到另一个本地目录,称为克隆目录。CLONE LOCAL 语句将本地 MySQL 服务器实例上的数据目录克隆到另一个本地目录,称为克隆目录。

本地克隆操作将数据从启动克隆操作的 MySQL 服务器实例克隆到运行 MySQL 服务器实例的同一服务器或节点上的目录。

图 7.2 远程克隆操作

从本地接收方 MySQL 服务器实例发出的 CLONE INSTANCE 语句将远程捐赠方 MySQL 服务器实例上的数据目录克隆到本地接收方 MySQL 服务器实例上的数据目录。从本地接收方 MySQL 服务器实例发出的 CLONE INSTANCE 语句将远程捐赠方 MySQL 服务器实例上的数据目录克隆到本地接收方 MySQL 服务器实例上的数据目录。

远程克隆操作涉及本地 MySQL 服务器实例(“接收方”),在该实例上启动克隆操作,并远程 MySQL 服务器实例(“捐赠方”),源数据位于该实例上。当在接收方上启动远程克隆操作时,克隆数据通过网络从捐赠方传输到接收方。默认情况下,远程克隆操作会在从捐赠方克隆数据之前,从接收方数据目录中删除现有的用户创建的数据(模式、表、表空间)和二进制日志。可选地,您可以将数据克隆到接收方的不同目录,以避免从当前接收方数据目录中删除数据。

通过本地克隆操作克隆的数据与通过远程克隆操作克隆的数据没有任何区别。这两种操作都会克隆相同的数据集。

克隆插件支持复制。除了克隆数据外,克隆操作还会从捐赠者中提取和传输复制坐标,并在接收者上应用这些坐标,从而使克隆插件能够为配置组复制成员和副本提供服务。使用克隆插件进行配置比复制大量事务要快得多且更有效(请参阅第 7.6.7.7 节,“用于复制的克隆”)。组复制成员还可以配置为使用克隆插件作为恢复的替代方法,以便成员自动选择从种子成员检索组数据的最有效方式。有关更多信息,请参阅第 20.5.4.2 节,“用于分布式恢复的克隆”。

克隆插件支持克隆加密和页面压缩的数据。请参阅第 7.6.7.5 节,“克隆加密数据”,以及第 7.6.7.6 节,“克隆压缩数据”。

在使用克隆插件之前,必须先安装它。有关安装说明,请参阅第 7.6.7.1 节,“安装克隆插件”。有关克隆说明,请参阅第 7.6.7.2 节,“本地数据克隆”,以及第 7.6.7.3 节,“远程数据克隆”。

提供了用于监视克隆操作的性能模式表和工具。请参阅第 7.6.7.10 节,“监视克隆操作”。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-installation.html

7.6.7.1 安装克隆插件

本节描述了如何安装和配置克隆插件。对于远程克隆操作,克隆插件必须安装在捐赠者和接收者 MySQL 服务器实例上。

有关安装或卸载插件的一般信息,请参见 Section 7.6.1, “Installing and Uninstalling Plugins”。

要使服务器可用,插件库文件必须位于 MySQL 插件目录中(由 plugin_dir 系统变量命名的目录)。如有必要,在服务器启动时设置 plugin_dir 的值,告诉服务器插件目录的位置。

插件库文件基本名称为 mysql_clone.so。文件名后缀因平台而异(例如,Unix 和类 Unix 系统使用 .so,Windows 使用 .dll)。

要在服务器启动时加载插件,请使用 --plugin-load-add 选项命名包含插件的库文件。使用此插件加载方法,每次服务器启动时都必须提供该选项。例如,将以下行放入您的 my.cnf 文件中,根据需要调整插件库文件名扩展名以适应您的平台。(插件库文件名扩展名取决于您的平台。Unix 和类 Unix 系统通常使用 .so,Windows 使用 .dll。)

代码语言:javascript复制
[mysqld]
plugin-load-add=mysql_clone.so

修改 my.cnf 后,重新启动服务器以使新设置生效。

注意

--plugin-load-add 选项在升级过程中重新启动服务器时无法用于加载克隆插件。例如,在从先前的 MySQL 版本升级到 MySQL 8.0 后,尝试使用 plugin-load-add=mysql_clone.so 重新启动服务器会导致以下错误:[ERROR] [MY-013238] [Server] Error installing plugin ‘clone’: Cannot install during upgrade。解决方法是在尝试使用 plugin-load-add=mysql_clone.so 启动服务器之前先升级服务器。

或者,要在运行时加载插件,请使用以下语句,根据需要调整平台的 .so 后缀:

代码语言:javascript复制
INSTALL PLUGIN clone SONAME 'mysql_clone.so';

INSTALL PLUGIN 加载插件,并在 mysql.plugins 系统表中注册,以使插件在每次正常服务器启动时自动加载,无需 --plugin-load-add

要验证插件安装情况,请检查信息模式PLUGINS表,或者使用SHOW PLUGINS语句(参见 Section 7.6.2, “Obtaining Server Plugin Information”)。例如:

代码语言:javascript复制
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME = 'clone';
 ------------------------ --------------- 
| PLUGIN_NAME            | PLUGIN_STATUS |
 ------------------------ --------------- 
| clone                  | ACTIVE        |
 ------------------------ --------------- 

如果插件初始化失败,请检查服务器错误日志以获取克隆或插件相关的诊断消息。

如果插件之前已经使用INSTALL PLUGIN注册过,或者使用--plugin-load-add加载过,您可以在服务器启动时使用--clone选项来控制插件的激活状态。例如,要在启动时加载插件并防止在运行时被移除,可以使用以下选项:

代码语言:javascript复制
[mysqld]
plugin-load-add=mysql_clone.so
clone=FORCE_PLUS_PERMANENT

如果您希望防止服务器在没有克隆插件的情况下运行,请使用--clone并设置值为FORCEFORCE_PLUS_PERMANENT,以强制服务器启动失败,如果插件初始化失败。

有关插件激活状态的更多信息,请参阅 Controlling Plugin Activation State。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-local.html

7.6.7.2 本地克隆数据

克隆插件支持以下语法用于本地克隆数据;即从本地 MySQL 数据目录克隆数据到同一服务器或节点上的另一个目录:

代码语言:javascript复制
CLONE LOCAL DATA DIRECTORY [=] '*clone_dir*';

要使用CLONE语法,必须安装克隆插件。有关安装说明,请参见第 7.6.7.1 节,“安装克隆插件”。

执行CLONE LOCAL DATA DIRECTORY语句需要*BACKUP_ADMIN*权限。

代码语言:javascript复制
mysql> GRANT BACKUP_ADMIN ON *.* TO '*clone_user*';

其中*clone_user*是执行克隆操作的 MySQL 用户。您选择执行克隆操作的用户可以是具有*BACKUP_ADMIN*权限的任何 MySQL 用户。

以下示例演示了本地克隆数据的操作:

代码语言:javascript复制
mysql> CLONE LOCAL DATA DIRECTORY = '*/path/to/clone_dir*';

其中*/path/to/clone_dir是数据被克隆到的本地目录的完整路径。需要绝对路径,并且指定的目录(“clone_dir*”)不得存在,但指定路径必须是一个已存在的路径。MySQL 服务器必须具有必要的写访问权限以创建目录。

注意

本地克隆操作不支持克隆存储在数据目录之外的用户创建的表或表空间。尝试克隆这样的表或表空间会导致以下错误:ERROR 1086 (HY000): File ‘/path/to/tablespace_name.ibd’ already exists. 尝试克隆具有与源表空间相同路径的表空间会导致冲突,因此被禁止。

所有其他用户创建的InnoDB表和表空间,InnoDB系统表空间,重做日志和撤销表空间都会被克隆到指定目录。

如果需要,您可以在克隆操作完成后在克隆目录上启动 MySQL 服务器。

代码语言:javascript复制
$> mysqld_safe --datadir=*clone_dir*

其中*clone_dir*是数据被克隆到的目录。

有关监视克隆操作状态和进度的信息,请参见第 7.6.7.10 节,“监视克隆操作”。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-remote.html

7.6.7.3 克隆远程数据

克隆插件支持以下语法用于克隆远程数据;即从远程 MySQL 服务器实例(捐赠者)克隆数据并将其传输到发起克隆操作的 MySQL 实例(接收方)。

代码语言:javascript复制
CLONE INSTANCE FROM '*user*'@'*host*':*port*
IDENTIFIED BY '*password*'
[DATA DIRECTORY [=] '*clone_dir*']
[REQUIRE [NO] SSL];

其中:

  • *user*是在捐赠者 MySQL 服务器实例上的克隆用户。
  • *password**user*的密码。
  • *host*是捐赠者 MySQL 服务器实例的主机名地址。不支持 Internet 协议版本 6(IPv6)地址格式。可以使用 IPv6 地址的别名。IPv4 地址可以直接使用。
  • *port*是捐赠者 MySQL 服务器实例的端口号。(不支持由mysqlx_port指定的 X 协议端口。也不支持通过 MySQL 路由器连接到捐赠者 MySQL 服务器实例。)
  • DATA DIRECTORY [=] '*clone_dir*'是一个可选子句,用于指定您正在克隆的数据在接收方的目录。如果不想从接收方数据目录中删除现有的用户创建数据(模式、表、表空间)和二进制日志,则使用此选项。需要绝对路径,并且目录不能存在。MySQL 服务器必须具有必要的写访问权限以创建目录。 当不使用可选的DATA DIRECTORY [=] '*clone_dir*'子句时,克隆操作会从接收方数据目录中删除用户创建的数据(模式、表、表空间)和二进制日志,将新数据克隆到接收方数据目录,并在之后自动重新启动服务器。
  • [REQUIRE [NO] SSL]明确指定在通过网络传输克隆数据时是否使用加密连接。如果无法满足明确规定,将返回错误。如果未指定 SSL 子句,默认情况下,克隆尝试建立加密连接,如果安全连接尝试失败,则退回到不安全连接。无论是否指定了此子句,克隆加密数据时都需要安全连接。有关更多信息,请参见为克隆配置加密连接。

注意

默认情况下,位于捐赠者 MySQL 服务器实例数据目录中的用户创建的InnoDB表和表空间将被克隆到接收者 MySQL 服务器实例的数据目录中。如果指定了DATA DIRECTORY [=] '*clone_dir*'子句,则它们将被克隆到指定目录。

用户创建的InnoDB表和表空间,如果位于捐赠 MySQL 服务器实例上的数据目录之外,则会被克隆到接收 MySQL 服务器实例上的相同路径。如果表或表空间已经存在,则会报告错误。

默认情况下,InnoDB系统表空间、重做日志和撤销表空间会被克隆到在捐赠端配置的相同位置(由innodb_data_home_dirinnodb_data_file_pathinnodb_log_group_home_dirinnodb_undo_directory定义)。如果指定了DATA DIRECTORY [=] '*clone_dir*'子句,则这些表空间和日志会被克隆到指定目录。

远程克隆先决条件

要执行克隆操作,克隆插件必须在捐赠端和接收端的 MySQL 服务器实例上处于活动状态。有关安装说明,请参阅 Section 7.6.7.1, “Installing the Clone Plugin”。

在捐赠端和接收端需要一个 MySQL 用户来执行克隆操作(“克隆用户”)。

  • 在捐赠端,克隆用户需要BACKUP_ADMIN权限,以便在克隆操作期间访问和传输来自捐赠端的数据,并阻止并发的 DDL。在 MySQL 8.0.27 之前,克隆操作期间会在捐赠端阻止并发的 DDL。从 MySQL 8.0.27 开始,默认情况下在捐赠端允许并发的 DDL。请参阅 Section 7.6.7.4, “Cloning and Concurrent DDL”。
  • 在接收端,克隆用户需要CLONE_ADMIN权限来替换接收端数据,在克隆操作期间阻止 DDL,并自动重新启动服务器。CLONE_ADMIN权限隐含包括BACKUP_ADMINSHUTDOWN权限。

包括创建克隆用户和授予所需权限的说明在接下来的远程克隆示例中。

当执行CLONE INSTANCE语句时,会检查以下先决条件:

克隆插件在 MySQL 8.0.17 及更高版本中受支持。捐赠端和接收端必须是相同的 MySQL 服务器系列,例如 8.0.37 和 8.0.41。在 8.0.37 之前的版本中,它们必须是相同的点发布版本。

代码语言:javascript复制
mysql> SHOW VARIABLES LIKE 'version';
  --------------- -------- 
| Variable_name | Value  |
 --------------- -------- 
| version       | 8.0.36 |
 --------------- -------- 

从捐赠 MySQL 服务器实例克隆到相同版本和发布版本的热修复 MySQL 服务器实例在 MySQL 8.0.26 中得到支持。

从系列内不同的点发布版本克隆是从 MySQL 8.0.37 开始支持的。对于早于 8.0.37 的版本,仍然适用先前的限制。例如,不允许将 8.0.36 克隆到 8.0.42 或反之亦然。

捐赠者和接收方 MySQL 服务器实例必须在相同的操作系统和平台上运行。例如,如果捐赠者实例在 Linux 64 位平台上运行,则接收方实例也必须在该平台上运行。请参考您的操作系统文档以了解如何确定您的操作系统平台。

接收方必须有足够的磁盘空间来存储克隆的数据。默认情况下,在克隆捐赠者数据之前,接收方会删除用户创建的数据(模式、表、表空间)和二进制日志,因此您只需要足够的空间来存储捐赠者数据。如果您使用DATA DIRECTORY子句克隆到命名目录,则必须有足够的磁盘空间来存储现有接收方数据和克隆的数据。您可以通过检查文件系统上的数据目录大小和驻留在数据目录之外的任何表空间的大小来估算数据大小。在估算捐赠者的数据大小时,请记住只有InnoDB数据会被克隆。如果您在其他存储引擎中存储数据,请相应调整数据大小的估算。

InnoDB允许在数据目录之外创建一些表空间类型。如果捐赠者 MySQL 服务器实例具有驻留在数据目录之外的表空间,则克隆操作必须能够访问这些表空间。您可以查询信息模式FILES表来识别驻留在数据目录之外的表空间。驻留在数据目录之外的文件具有指向数据目录以外目录的完全限定路径。

代码语言:javascript复制
mysql> SELECT FILE_NAME FROM INFORMATION_SCHEMA.FILES;

在捐赠者上激活的插件,包括任何密钥环插件,也必须在接收方上激活。您可以通过发出SHOW PLUGINS语句或查询信息模式PLUGINS表来识别活动插件。

捐赠者和接收方必须具有相同的 MySQL 服务器字符集和校对规则。有关 MySQL 服务器字符集和校对规则配置的信息,请参见第 12.15 节,“字符集配置”。

捐赠者和接收者必须具有相同的innodb_page_sizeinnodb_data_file_path设置。捐赠者和接收者的innodb_data_file_path设置必须指定相同数量的等效大小的数据文件。您可以使用SHOW VARIABLES语法检查变量设置。

代码语言:javascript复制
mysql> SHOW VARIABLES LIKE 'innodb_page_size';
mysql> SHOW VARIABLES LIKE 'innodb_data_file_path';

如果克隆加密或页面压缩数据,则捐赠者和接收者必须具有相同的文件系统块大小。对于页面压缩数据,接收方文件系统必须支持稀疏文件和孔打孔,以便在接收方上进行孔打孔。有关这些功能以及如何识别使用这些功能的表和表空间的信息,请参见 Section 7.6.7.5,“克隆加密数据”和 Section 7.6.7.6,“克隆压缩数据”。要确定您的文件系统块大小,请参考您的操作系统文档。

如果要克隆加密数据,则需要安全连接。请参见为克隆配置加密连接。

接收方的clone_valid_donor_list设置必须包括捐赠者 MySQL 服务器实例的主机地址。您只能从有效捐赠者列表中的主机克隆数据。需要具有SYSTEM_VARIABLES_ADMIN权限的 MySQL 用户来配置此变量。在本节之后的远程克隆示例中提供了设置clone_valid_donor_list变量的说明。您可以使用SHOW VARIABLES语法检查clone_valid_donor_list设置。

代码语言:javascript复制
mysql> SHOW VARIABLES LIKE 'clone_valid_donor_list';

不得运行其他克隆操作。一次只允许进行单个克隆操作。要确定是否正在运行克隆操作,请查询clone_status表。请参见使用性能模式克隆表监视克隆操作。

克隆插件以 1MB 数据包加元数据的方式传输数据。因此,捐赠者和接收方 MySQL 服务器实例上最低要求的max_allowed_packet值为 2MB。小于 2MB 的max_allowed_packet值会导致错误。使用以下查询检查您的max_allowed_packet设置:

代码语言:javascript复制
mysql> SHOW VARIABLES LIKE 'max_allowed_packet';

还有以下先决条件:

捐赠者上的撤销表空间文件名必须是唯一的。当数据克隆到接收方时,无论在捐赠者上的位置如何,撤销表空间都会克隆到接收方的innodb_undo_directory位置或使用DATA DIRECTORY [=] '*clone_dir*'子句指定的目录。由于这个原因,捐赠者上重复的撤销表空间文件名是不允许的。从 MySQL 8.0.18 开始,在克隆操作期间遇到重复的撤销表空间文件名时会报告错误。在 MySQL 8.0.18 之前,克隆具有相同文件名的撤销表空间可能会导致接���方上的撤销表空间文件被覆盖。

要查看捐赠者上的撤销表空间文件名以确保它们是唯一的,请查询INFORMATION_SCHEMA.FILES

代码语言:javascript复制
mysql> SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES
       WHERE FILE_TYPE LIKE 'UNDO LOG';

有关删除和添加撤销表空间文件的信息,请参见 Section 17.6.3.4,“撤销表空间”。

默认情况下,在数据克隆后,接收方 MySQL 服务器实例会自动重启(停止和启动)。要实现自动重启,接收方必须有一个监控进程来检测服务器的关闭。否则,在数据克隆后,克隆操作会因为以下错误而停止,并且接收方 MySQL 服务器实例会关闭:

代码语言:javascript复制
ERROR 3707 (HY000): Restart server failed (mysqld is not managed by supervisor process).

此错误并不表示克隆失败。这意味着在数据克隆后,接收方 MySQL 服务器实例必须手动重新启动。在手动启动服务器后,您可以连接到接收方 MySQL 服务器实例,并检查性能模式克隆表,以验证克隆操作是否成功完成(请参见使用性能模式克隆表监控克隆操作)。RESTART语句也具有相同的监控进程要求。有关更多信息,请参见 Section 15.7.8.8,“RESTART Statement”。如果使用DATA DIRECTORY子句克隆到命名目录,则不适用此要求,因为在这种情况下不会执行自动重启。

几个变量控制远程克隆操作的各个方面。在执行远程克隆操作之前,请查看这些变量并根据需要调整设置以适应您的计算环境。克隆变量设置在执行克隆操作的接收方 MySQL 服务器实例上。请参阅 Section 7.6.7.13, “克隆系统变量”。

克隆远程数据

以下示例演示了克隆远程数据的过程。默认情况下,远程克隆操作会在接收方上删除用户创建的数据(模式、表、表空间)和二进制日志,将新数据克隆到接收方数据目录,并在之后重新启动 MySQL 服务器。

本示例假定远程克隆的先决条件已满足。请参阅远程克隆先决条件。

使用管理员用户帐户登录到捐赠方 MySQL 服务器实例。

创建一个具有BACKUP_ADMIN权限的克隆用户。

代码语言:javascript复制
mysql> CREATE USER 'donor_clone_user'@'example.donor.host.com' IDENTIFIED BY '*password*';
mysql> GRANT BACKUP_ADMIN on *.* to 'donor_clone_user'@'example.donor.host.com';

安装克隆插件:

代码语言:javascript复制
mysql> INSTALL PLUGIN clone SONAME 'mysql_clone.so';

使用管理员用户帐户登录到接收方 MySQL 服务器实例。

创建一个具有CLONE_ADMIN权限的克隆用户。

代码语言:javascript复制
mysql> CREATE USER 'recipient_clone_user'@'example.recipient.host.com' IDENTIFIED BY '*password*';
mysql> GRANT CLONE_ADMIN on *.* to 'recipient_clone_user'@'example.recipient.host.com';

安装克隆插件:

代码语言:javascript复制
mysql> INSTALL PLUGIN clone SONAME 'mysql_clone.so';

将捐赠方 MySQL 服务器实例的主机地址添加到clone_valid_donor_list变量设置中。

代码语言:javascript复制
mysql> SET GLOBAL clone_valid_donor_list = '*example.donor.host.com*:*3306*';

以前创建的克隆用户(recipient_clone_user'@'example.recipient.host.com)登录到接收方 MySQL 服务器实例,并执行CLONE INSTANCE语句。

代码语言:javascript复制
mysql> CLONE INSTANCE FROM 'donor_clone_user'@'example.donor.host.com':3306
       IDENTIFIED BY '*password*';

数据克隆完成后,接收方 MySQL 服务器实例将自动重新启动。

有关监视克隆操作状态和进度的信息,请参见 Section 7.6.7.10, “监视克隆操作”。

克隆到指定目录

默认情况下,远程克隆操作会在克隆数据之前从接收方数据目录中删除用户创建的数据(模式、表、表空间)和二进制日志。通过克隆到指定目录,您可以避免从当前接收方数据目录中删除数据。

克隆到指定目录的过程与克隆远程数据中描述的过程相同,唯一的例外是:CLONE INSTANCE语句必须包含DATA DIRECTORY子句。例如:

代码语言:javascript复制
mysql> CLONE INSTANCE FROM '*user*'@'*example.donor.host.com*':*3306*
       IDENTIFIED BY '*password*'
       DATA DIRECTORY = '*/path/to/clone_dir*';

需要绝对路径,并且目录不能存在。MySQL 服务器必须具有必要的写访问权限以创建目录。

在克隆到命名目录时,接收方 MySQL 服务器实例在克隆数据后不会自动重新启动。如果要在命名目录上重新启动 MySQL 服务器,则必须手动执行:

代码语言:javascript复制
$> mysqld_safe --datadir=*/path/to/clone_dir*

其中*/path/to/clone_dir*是接收方命名目录的路径。

为克隆配置加密连接

您可以配置远程克隆操作的加密连接,以保护在网络上传输时克隆的数据。默认情况下,当克隆加密数据时需要加密连接。(参见第 7.6.7.5 节,“克隆加密数据”。)

接下来的说明描述了如何配置接收方 MySQL 服务器实例以使用加密连接。假定捐赠方 MySQL 服务器实例已配置为使用加密连接。如果没有,请参考第 8.3.1 节,“配置 MySQL 使用加密连接”进行服务器端配置说明。

要配置接收方 MySQL 服务器实例以使用加密连接:

使捐赠方 MySQL 服务器实例的客户端证书和密钥文件可供接收方主机使用。可以通过安全通道将文件分发到接收方主机,或将它们放在对接收方主机可访问的挂载分区上。要提供的客户端证书和密钥文件包括:

  • ca.pem 自签名证书颁发机构(CA)文件。
  • client-cert.pem 客户端公钥证书文件。
  • client-key.pem 客户端私钥文件。

在接收方 MySQL 服务器实例上配置以下 SSL 选项。

  • clone_ssl_ca 指定自签名证书颁发机构(CA)文件的路径。
  • clone_ssl_cert 指定客户端公钥证书文件的路径。
  • clone_ssl_key 指定客户端私钥文件的路径。

例如:

代码语言:javascript复制
clone_ssl_ca=/*path*/*to*/ca.pem
clone_ssl_cert=/*path*/*to*/client-cert.pem
clone_ssl_key=/*path*/*to*/client-key.pem

要求使用加密连接,请在接收方发出CLONE语句时包含REQUIRE SSL子句。

代码语言:javascript复制
mysql> CLONE INSTANCE FROM '*user*'@'*example.donor.host.com*':*3306*
       IDENTIFIED BY '*password*'
       DATA DIRECTORY = '*/path/to/clone_dir*'
       REQUIRE SSL;

如果未指定 SSL 子句,则克隆插件默认尝试建立加密连接,如果加密连接尝试失败,则回退到非加密连接。

注意

如果您正在克隆加密数据,则默认情况下需要加密连接,无论是否指定了REQUIRE SSL子句。使用REQUIRE NO SSL会在尝试克隆加密数据时导致错误。

译文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-concurrent-ddl.html

7.6.7.4 克隆和并发 DDL

在 MySQL 8.0.27 之前,在克隆操作期间,包括TRUNCATE TABLE在内的捐赠者和接收者 MySQL 服务器实例上的 DDL 操作是不允许的。在选择数据源时应考虑此限制。一种解决方法是使用专用的捐赠者实例,可以在克隆数据时阻止 DDL 操作。

为防止在克隆操作期间进行并发 DDL,捐赠者和接收者上会获取独占的备份锁。clone_ddl_timeout变量定义了在捐赠者和接收者上,克隆操作等待备份锁的时间(以秒为单位)。默认设置为 300 秒。如果在指定的时间限制内未获得备份锁,则克隆操作将因错误而失败。

从 MySQL 8.0.27 开始,默认情况下允许在捐赠者上进行并发 DDL。捐赠者上的并发 DDL 支持由clone_block_ddl变量控制。可以使用SET语句动态启用和禁用捐赠者上的并发 DDL 支持。

代码语言:javascript复制
SET GLOBAL clone_block_ddl={OFF|ON}

默认设置为clone_block_ddl=OFF,允许在捐赠者上进行并发 DDL。

并发 DDL 操作的效果是否被克隆取决于 DDL 操作是否在克隆操作获取动态快照之前完成。

不允许在克隆操作期间进行的 DDL 操作,无论clone_block_ddl设置如何,包括:

  • ALTER TABLE *tbl_name* DISCARD TABLESPACE;
  • ALTER TABLE *tbl_name* IMPORT TABLESPACE;
  • ALTER INSTANCE DISABLE INNODB REDO_LOG;

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-encrypted-data.html

7.6.7.5 克隆加密数据

支持对加密数据进行克隆。以下要求适用:

  • 在将远程数据克隆时,需要安全连接以确保未加密表空间密钥在网络上传输时的安全性。表空间密钥在捐赠者处解密后传输,并在接收者处使用接收者主密钥重新加密。如果没有加密连接可用或在 CLONE INSTANCE 语句中使用 REQUIRE NO SSL 子句,则会报告错误。有关为克隆配置加密连接的信息,请参见 为克隆配置加密连接。
  • 当将数据克隆到使用本地管理的密钥环的本地数据目录时,启动克隆目录上的 MySQL 服务器时必须使用相同的密钥环。
  • 当将数据克隆到使用本地管理的密钥环的远程数据目录(接收者目录)时,启动克隆目录上的 MySQL 服务器时必须使用接收者密钥环。

注意

innodb_redo_log_encryptinnodb_undo_log_encrypt 变量设置在克隆操作进行时无法修改。

有关数据加密功能的信息,请参见 第 17.13 节,“InnoDB 数据静态加密”。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-compressed-data.html

7.6.7.6 克隆压缩数据

支持对页面压缩数据进行克隆。在克隆远程数据时,需要满足以下要求:

  • 接收方文件系统必须支持稀疏文件和空洞打孔,以便在接收方上进行空洞打孔。
  • 捐赠方和接收方文件系统必须具有相同的块大小。如果文件系统块大小不同,则会报告类似以下错误:ERROR 3868 (HY000): Clone Configuration FS Block Size: Donor value: 114688 is different from Recipient value: 4096.

关于页面压缩功能的信息,请参见第 17.9.2 节,“InnoDB 页面压缩”。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-replication.html

7.6.7.7 复制用的克隆

克隆插件支持复制。除了克隆数据外,克隆操作还会从捐赠者提取复制坐标并将其传输给接收者,这使得可以使用克隆插件为配置组复制成员和副本提供服务。使用克隆插件进行配置比复制大量事务要快得多且更有效率。

配置组复制成员也可以配置为使用克隆插件作为分布式恢复的选项,这样加入成员会自动选择从现有组成员检索组数据的最有效方式。有关更多信息,请参见 Section 20.5.4.2, “Cloning for Distributed Recovery”。

在克隆操作期间,二进制日志位置(文件名、偏移量)和gtid_executed GTID 集都会从捐赠者的 MySQL 服务器实例中提取并传输到接收者。这些数据允许在复制流中的一致位置启动复制。二进制日志和中继日志(保存在文件中)不会从捐赠者复制到接收者。为了启动复制,接收者需要的二进制日志必须在数据克隆和启动复制之间不被清除。如果所需的二进制日志不可用,则会报告复制握手错误。因此,克隆实例应尽快添加到复制组中,以避免所需的二进制日志被清除或新成员明显滞后,需要更多的恢复时间。

在克隆的 MySQL 服务器实例上执行此查询,以检查已传输给接收者的二进制日志位置:

代码语言:javascript复制
mysql> SELECT BINLOG_FILE, BINLOG_POSITION FROM performance_schema.clone_status;

在克隆的 MySQL 服务器实例上执行此查询,以检查已传输给接收者的gtid_executed GTID 集:

代码语言:javascript复制
mysql> SELECT @@GLOBAL.GTID_EXECUTED;

在 MySQL 8.0 中,默认情况下,复制元数据存储库保存在在克隆操作期间从捐赠者复制到接收者的表中。复制元数据存储库保存了可以在克隆操作后正确恢复复制的与复制相关的配置设置。

  • 在 MySQL 8.0.17 和 8.0.18 中,只会复制表 mysql.slave_master_info(连接元数据存储库)。
  • 从 MySQL 8.0.19 开始,表 mysql.slave_relay_log_info(应用程序元数据存储库)和 mysql.slave_worker_info(应用程序工作程序元数据存储库)也会被复制。

要查看每个表中包含的内容列表,请参阅 Section 19.2.4.2, “Replication Metadata Repositories”。请注意,如果服务器上使用了设置 master_info_repository=FILErelay_log_info_repository=FILE(这在 MySQL 8.0 中不是默认设置且已被弃用),则不会克隆复制元数据存储库;只有在设置为 TABLE 时才会克隆。

要进行复制克隆,请执行以下步骤:

对于 Group Replication 的新成员,首先按照 Section 20.2.1.6, “Adding Instances to the Group” 中的说明配置 MySQL Server 实例以进行 Group Replication。同时,设置克隆的先决条件,详见 Section 20.5.4.2, “Cloning for Distributed Recovery”。当在加入成员上发出 START GROUP_REPLICATION 命令时,克隆操作将由 Group Replication 自动管理,因此您无需手动执行操作,也无需在加入成员上执行任何进一步的设置步骤。

对于源/复制 MySQL 复制拓扑中的副本,首先手动将数据从捐赠方 MySQL 服务器实例克隆到接收方。捐赠方必须是复制拓扑中的源或副本。有关克隆说明,请参阅 Section 7.6.7.3, “Cloning Remote Data”。

克隆操作成功完成后,如果您希望在接收方 MySQL 服务器实例上使用与捐赠方相同的复制通道,请验证哪些通道可以在源/复制 MySQL 复制拓扑中自动恢复复制,哪些需要手动设置。

  • 对于基于 GTID 的复制,如果接收方配置为 gtid_mode=ON 并且从配置为 gtid_mode=ONON_PERMISSIVEOFF_PERMISSIVE 的捐赠方克隆,那么从捐赠方应用 gtid_executed GTID 集到接收方。如果接收方是从已在拓扑中的副本克隆而来,那么在克隆操作后,使用 GTID 自动定位的复制通道可以在启动通道后自动恢复复制。如果您只想使用这些相同通道,则无需执行任何手动设置。
  • 对于基于二进制日志文件位置的复制,如果接收端是 MySQL 8.0.17 或 8.0.18,则从提供端的二进制日志位置不会应用到接收端,只会记录在性能模式 clone_status 表中。因此,接收端上使用基于二进制日志文件位置的复制通道必须手动设置以在克隆操作后恢复复制。确保这些通道未配置为在服务器启动时自动开始复制,因为它们尚未具有二进制日志位置,并尝试从头开始复制。
  • 对于基于二进制日志文件位置的复制,如果接收端是 MySQL 8.0.19 或更高版本,则从提供端应用二进制日志位置到接收端。接收端上使用基于二进制日志文件位置的复制通道会自动尝试执行中继日志恢复过程,使用克隆的中继日志信息,在重新启动复制之前。对于单线程副本(replica_parallel_workersslave_parallel_workers 设置为 0),在没有其他问题的情况下,中继日志恢复应该成功,使通道能够在没有进一步设置的情况下恢复复制。对于多线程副本(replica_parallel_workersslave_parallel_workers 大于 0),中继日志恢复可能会失败,因为通常无法自动完成。在这种情况下,会发出错误消息,您必须手动设置通道。

如果您需要手动设置克隆复制通道,或者希望在接收端使用不同的复制通道,以下说明提供了一个摘要和简化示例,用于将接收端 MySQL 服务器实例添加到复制拓扑中。还请参考适用于您的复制设置的详细说明。

要将一个接收方 MySQL 服务器实例添加到使用基于 GTID 的事务作为复制数据源的 MySQL 复制拓扑中,请根据需要配置实例,并按照 Section 19.1.3.4,“使用 GTID 设置复制”中的说明操作。按照以下简化示例为实例添加复制通道。CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)必须定义源的主机地址和端口号,并且应启用SOURCE_AUTO_POSITION | MASTER_AUTO_POSITION选项,如下所示:

代码语言:javascript复制
mysql> CHANGE MASTER TO MASTER_HOST = '*source_host_name*', MASTER_PORT = *source_port_num*,
       ...
       MASTER_AUTO_POSITION = 1,
       FOR CHANNEL '*setup_channel*';
mysql> START SLAVE USER = '*user_name*' PASSWORD = '*password*' FOR CHANNEL '*setup_channel*';

Or from MySQL 8.0.22 and 8.0.23:

mysql> CHANGE SOURCE TO SOURCE_HOST = '*source_host_name*', SOURCE_PORT = *source_port_num*,
       ...
       SOURCE_AUTO_POSITION = 1,
       FOR CHANNEL '*setup_channel*';
mysql> START REPLICA USER = '*user_name*' PASSWORD = '*password*' FOR CHANNEL '*setup_channel*';

要将一个接收方 MySQL 服务器实例添加到使用基于二进制日志文件位置的复制的 MySQL 复制拓扑中,请根据需要配置实例,并按照 Section 19.1.2,“设置基于二进制日志文件位置的复制”中的说明操作。按照以下简化示例为实例添加复制通道,使用在克隆操作期间传输给接收方的二进制日志位置:

代码语言:javascript复制
mysql> SELECT BINLOG_FILE, BINLOG_POSITION FROM performance_schema.clone_status;
mysql> CHANGE MASTER TO MASTER_HOST = '*source_host_name*', MASTER_PORT = *source_port_num*,
       ...
       MASTER_LOG_FILE = '*source_log_name*',
       MASTER_LOG_POS = *source_log_pos*,
       FOR CHANNEL '*setup_channel*';
mysql> START SLAVE USER = '*user_name*' PASSWORD = '*password*' FOR CHANNEL '*setup_channel*';

Or from MySQL 8.0.22 and 8.0.23:

mysql> SELECT BINLOG_FILE, BINLOG_POSITION FROM performance_schema.clone_status;
mysql> CHANGE SOURCE TO SOURCE_HOST = '*source_host_name*', SOURCE_PORT = *source_port_num*,
       ...
       SOURCE_LOG_FILE = '*source_log_name*',
       SOURCE_LOG_POS = *source_log_pos*,
       FOR CHANNEL '*setup_channel*';
mysql> START REPLICA USER = '*user_name*' PASSWORD = '*password*' FOR CHANNEL '*setup_channel*';

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-directories.html

7.6.7.8 克隆操作期间创建的目录和文件

当数据被克隆时,以下目录和文件会被创建用于内部使用。不应该被修改。

  • #clone:包含克隆操作使用的内部克隆文件。在数据被克隆到的目录中创建。
  • #ib_archive:包含在克隆操作期间在捐赠者上归档的内部归档日志文件。
  • *.#clone 文件:在接收端创建的临时数据文件,当数据从接收端数据目录中移除并在远程克隆操作期间克隆新数据时创建。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-failure-handling.html

7.6.7.9 远程克隆操作失败处理

本节描述了克隆操作在不同阶段的失败处理。

先决条件被检查(参见远程克隆先决条件)。

  • 如果在先决条件检查期间发生故障,则CLONE INSTANCE操作会报告错误。

在 MySQL 8.0.27 之前,在提供方和接收方上备份锁会阻止并发的 DDL 操作。从 MySQL 8.0.27 开始,仅当clone_block_ddl变量设置为ON时(默认设置为OFF)才会阻止提供方上的并发 DDL。参见 Section 7.6.7.4, “Cloning and Concurrent DDL”。

  • 如果克隆操作无法在clone_ddl_timeout变量指定的时间限制内获得 DDL 锁,则会报告错误。

用户创建的数据(模式、表、表空间)和接收方上的二进制日志在将数据克隆到接收方数据目录之前被移除。

在远程克隆操作期间从接收方数据目录中移除用户创建的数据和二进制日志时,数据不会被保存,如果发生故障可能会丢失。如果数据很重要,应在启动远程克隆操作之前进行备份。

为了信息目的,警告会被打印到服务器错误日志中,以指定数据移除何时开始和结束:

代码语言:javascript复制
[Warning] [MY-013453] [InnoDB] Clone removing all user data for provisioning:
Started...

[Warning] [MY-013453] [InnoDB] Clone removing all user data for provisioning:
Finished

如果在移除数据时发生故障,接收方可能会留下部分在克隆操作之前存在的模式、表和表空间。在执行克隆操作期间或发生故障后的任何时候,服务器始终处于一致状态。

数据从提供方克隆。用户创建的数据、字典元数据和其他系统数据都会被克隆。

  • 如果在克隆数据时发生故障,克隆操作将被回滚并移除所有克隆数据。在此阶段,接收方上先前存在的用户创建的数据和二进制日志也已被移除。 如果发生这种情况,您可以纠正故障原因并重新执行克隆操作,或放弃克隆操作并从在克隆操作之前进行的备份中恢复接收方数据。

服务器会自动重启(适用于不克隆到命名目录的远程克隆操作)。在启动过程中,会执行典型的服务器启动任务。

  • 如果自动服务器重启失败,您可以手动重启服务器以完成克隆操作。

在 MySQL 8.0.24 之前,如果在克隆操作期间发生网络错误,且在五分钟内解决了错误,则操作会恢复。从 MySQL 8.0.24 开始,如果在捐赠实例上定义的clone_donor_timeout_after_network_failure变量指定的时间内解决了错误,则操作会恢复。clone_donor_timeout_after_network_failure的默认设置为 5 分钟,但支持 0 到 30 分钟的范围。如果操作未在分配的时间内恢复,则会中止并返回错误,捐赠者会删除快照。将设置为零会导致在发生网络错误时捐赠者立即删除快照。配置更长的超时时间允许更多时间解决网络问题,但也会增加捐赠实例上的增量大小,从而增加克隆恢复时间以及在克隆旨在作为副本或复制组成员时的复制延迟。

在 MySQL 8.0.24 之前,捐赠者线程在监听克隆协议命令时使用 MySQL Server wait_timeout 设置。因此,低wait_timeout设置可能导致长时间运行的远程克隆操作超时。从 MySQL 8.0.24 开始,克隆空闲超时设置为默认的wait_timeout设置,即 28800 秒(8 小时)。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-monitoring.html

7.6.7.10 监控克隆操作

本节描述了监控克隆操作的选项。

  • 使用性能模式克隆表监控克隆操作
  • 使用性能模式阶段事件监控克隆操作
  • 使用性能模式克隆工具监控克隆操作
  • Com_clone 状态变量
使用性能模式克隆表监控克隆操作

克隆操作可能需要一些时间才能完成,这取决于数据量和与数据传输相关的其他因素。您可以使用clone_statusclone_progress 性能模式表在接收 MySQL 服务器实例上监视克隆操作的状态和进度。

注意

clone_statusclone_progress 性能模式表仅可用于监视接收 MySQL 服务器实例上的克隆操作。要监视捐赠 MySQL 服务器实例上的克隆操作,请使用克隆阶段事件,如使用性能模式阶段事件监控克隆操作中所述。

  • clone_status 表提供当前或最近执行的克隆操作的状态。克隆操作有四种可能的状态:未开始进行中已完成失败
  • clone_progress 表提供当前或最近执行的克隆操作的进度信息,按阶段划分。克隆操作的阶段包括 DROP DATAFILE COPYPAGE_COPYREDO_COPYFILE_SYNCRESTARTRECOVERY

访问性能模式克隆表需要在性能模式上具有SELECTEXECUTE权限。

要检查克隆操作的状态:

连接到接收方 MySQL 服务器实例。

查询clone_status表:

代码语言:javascript复制
mysql> SELECT STATE FROM performance_schema.clone_status;
 ----------- 
| STATE     |
 ----------- 
| Completed |
 ----------- 

如果在克隆操作期间发生故障,您可以查询clone_status表以获取错误信息:

代码语言:javascript复制
mysql> SELECT STATE, ERROR_NO, ERROR_MESSAGE FROM performance_schema.clone_status;
 ----------- ---------- --------------- 
| STATE     | ERROR_NO | ERROR_MESSAGE |
 ----------- ---------- --------------- 
| Failed    |      xxx | "xxxxxxxxxxx" |
 ----------- ---------- --------------- 

要查看克隆操作的每个阶段的详细信息:

连接到接收方 MySQL 服务器实例。

查询clone_progress表。例如,以下查询提供了克隆操作每个阶段的状态和结束时间数据:

代码语言:javascript复制
mysql> SELECT STAGE, STATE, END_TIME FROM performance_schema.clone_progress;
 ----------- ----------- ---------------------------- 
| stage     | state     | end_time                   |
 ----------- ----------- ---------------------------- 
| DROP DATA | Completed | 2019-01-27 22:45:43.141261 |
| FILE COPY | Completed | 2019-01-27 22:45:44.457572 |
| PAGE COPY | Completed | 2019-01-27 22:45:44.577330 |
| REDO COPY | Completed | 2019-01-27 22:45:44.679570 |
| FILE SYNC | Completed | 2019-01-27 22:45:44.918547 |
| RESTART   | Completed | 2019-01-27 22:45:48.583565 |
| RECOVERY  | Completed | 2019-01-27 22:45:49.626595 |
 ----------- ----------- ---------------------------- 

要监视其他克隆状态和进度数据点,请参考第 29.12.19 节,“性能模式克隆表”。

使用性能模式阶段事件监视克隆操作

克隆操作可能需要一些时间才能完成,这取决于数据量和与数据传输相关的其他因素。有三个阶段事件用于监视克隆操作的进度。每个阶段事件报告 WORK_COMPLETEDWORK_ESTIMATED 值。随着操作的进行,报告的值会进行修订。

可以在捐赠方或接收方 MySQL 服务器实例上使用此方法监视克隆操作。

按发生顺序,克隆操作阶段事件包括:

  • stage/innodb/clone (file copy): 表示克隆操作的文件复制阶段的进度。WORK_ESTIMATEDWORK_COMPLETED 单位为文件块。在文件复制阶段开始时,就已知要传输的文件数量,并且根据文件数量估算出块的数量。WORK_ESTIMATED 设置为估计文件块的数量。每发送一个块后,WORK_COMPLETED 都会更新。
  • stage/innodb/clone (page copy): 表示克隆操作的页面复制阶段的进度。WORK_ESTIMATEDWORK_COMPLETED 单位为页面。一旦文件复制阶段完成,就会知道要传输的页面数量,并且将 WORK_ESTIMATED 设置为此值。每发送一个页面后,WORK_COMPLETED 都会更新。
  • stage/innodb/clone (redo copy): 表示克隆操作的重做复制阶段的进度。WORK_ESTIMATEDWORK_COMPLETED 单位为重做块。一旦页面复制阶段完成,就会知道要传输的重做块数量,并且 WORK_ESTIMATED 设置为此值。每发送一个块后,WORK_COMPLETED 都会更新。

以下示例演示了如何启用stage/innodb/clone%事件仪器和相关的消费者表来监视克隆操作。有关性能模式阶段事件仪器和相关消费者的信息,请参见第 29.12.5 节,“性能模式阶段事件表”。

启用stage/innodb/clone%仪器:

代码语言:javascript复制
mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES'
       WHERE NAME LIKE 'stage/innodb/clone%';

启用阶段事件消费者表,包括events_stages_currentevents_stages_historyevents_stages_history_long

代码语言:javascript复制
mysql> UPDATE performance_schema.setup_consumers SET ENABLED = 'YES'
       WHERE NAME LIKE '%stages%';

运行克隆操作。在此示例中,将本地数据目录克隆到名为cloned_dir的目录。

代码语言:javascript复制
mysql> CLONE LOCAL DATA DIRECTORY = '/path/to/cloned_dir';

通过查询性能模式events_stages_current表来检查克隆操作的进度。显示的阶段事件取决于正在进行的克隆阶段。WORK_COMPLETED列显示已完成的工作。WORK_ESTIMATED列显示总共需要的工作量。

代码语言:javascript复制
mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_current
       WHERE EVENT_NAME LIKE 'stage/innodb/clone%';
 -------------------------------- ---------------- ---------------- 
| EVENT_NAME                     | WORK_COMPLETED | WORK_ESTIMATED |
 -------------------------------- ---------------- ---------------- 
| stage/innodb/clone (redo copy) |              1 |              1 |
 -------------------------------- ---------------- ---------------- 

如果克隆操作已经完成,events_stages_current表将返回一个空集。在这种情况下,您可以检查events_stages_history表以查看已完成操作的事件数据。例如:

代码语言:javascript复制
mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_history
       WHERE EVENT_NAME LIKE 'stage/innodb/clone%';
 -------------------------------- ---------------- ---------------- 
| EVENT_NAME                     | WORK_COMPLETED | WORK_ESTIMATED |
 -------------------------------- ---------------- ---------------- 
| stage/innodb/clone (file copy) |            301 |            301 |
| stage/innodb/clone (page copy) |              0 |              0 |
| stage/innodb/clone (redo copy) |              1 |              1 |
 -------------------------------- ---------------- ---------------- 
使用性能模式克隆仪器监视克隆操作

性能模式提供了用于高级性能监控克隆操作的仪器。要查看可用的克隆仪器,并发出以下查询:

代码语言:javascript复制
mysql> SELECT NAME,ENABLED FROM performance_schema.setup_instruments
       WHERE NAME LIKE '%clone%';
 --------------------------------------------------- --------- 
| NAME                                              | ENABLED |
 --------------------------------------------------- --------- 
| wait/synch/mutex/innodb/clone_snapshot_mutex      | NO      |
| wait/synch/mutex/innodb/clone_sys_mutex           | NO      |
| wait/synch/mutex/innodb/clone_task_mutex          | NO      |
| wait/synch/mutex/group_rpl/LOCK_clone_donor_list  | NO      |
| wait/synch/mutex/group_rpl/LOCK_clone_handler_run | NO      |
| wait/synch/mutex/group_rpl/LOCK_clone_query       | NO      |
| wait/synch/mutex/group_rpl/LOCK_clone_read_mode   | NO      |
| wait/synch/cond/group_rpl/COND_clone_handler_run  | NO      |
| wait/io/file/innodb/innodb_clone_file             | YES     |
| stage/innodb/clone (file copy)                    | YES     |
| stage/innodb/clone (redo copy)                    | YES     |
| stage/innodb/clone (page copy)                    | YES     |
| statement/abstract/clone                          | YES     |
| statement/clone/local                             | YES     |
| statement/clone/client                            | YES     |
| statement/clone/server                            | YES     |
| memory/innodb/clone                               | YES     |
| memory/clone/data                                 | YES     |
 --------------------------------------------------- --------- 
等待仪器

性能模式等待仪器跟踪需要时间的事件。克隆等待事件仪器包括:

  • wait/synch/mutex/innodb/clone_snapshot_mutex:跟踪克隆快照互斥锁的等待事件,该互斥锁在多个克隆线程之间同步访问动态快照对象(在捐赠者和接收者之间)。
  • wait/synch/mutex/innodb/clone_sys_mutex:跟踪克隆系统互斥锁的等待事件。在 MySQL 服务器实例中有一个克隆系统对象。此互斥锁在捐赠者和接收者之间同步访问克隆系统对象。它由克隆线程和其他前台和后台线程获取。
  • wait/synch/mutex/innodb/clone_task_mutex:跟踪克隆任务互斥锁的等待事件,用于克隆任务管理。clone_task_mutex由克隆线程获取。
  • wait/io/file/innodb/innodb_clone_file: 跟踪克隆操作的文件上的所有 I/O 等待操作。

关于监控InnoDB互斥等待的信息,请参阅第 17.16.2 节,“使用性能模式监控 InnoDB 互斥等待”。关于一般监控等待事件的信息,请参阅第 29.12.4 节,“性能模式等待事件表”。

阶段工具

性能模式阶段事件跟踪语句执行过程中发生的步骤。克隆阶段事件工具包括:

  • stage/innodb/clone (file copy): 表示克隆操作的文件复制阶段的进度。
  • stage/innodb/clone (redo copy): 表示克隆操作的重做复制阶段的进度。
  • stage/innodb/clone (page copy): 表示克隆操作的页面复制阶段的进度。

关于使用阶段事件监控克隆操作的信息,请参阅使用性能模式阶段事件监控克隆操作。关于一般监控阶段事件的信息,请参阅第 29.12.5 节,“性能模式阶段事件表”。

语句工具

性能模式语句事件跟踪语句执行。当启动克隆操作时,由克隆语句工具跟踪的不同语句类型可能并行执行。您可以在性能模式语句事件表中观察这些语句事件。执行的语句数量取决于clone_max_concurrencyclone_autotune_concurrency设置。

克隆语句事件工具包括:

  • statement/abstract/clone: 跟踪在被分类为本地、客户端或服务器操作类型之前的任何克隆操作的语句事件。
  • statement/clone/local: 跟踪本地克隆操作的克隆语句事件;在执行CLONE LOCAL语句时生成。
  • statement/clone/client: 跟踪发生在接收端 MySQL 服务器实例上的远程克隆语句事件;在接收端执行CLONE INSTANCE语句时生成。
  • statement/clone/server: 跟踪发生在捐赠 MySQL 服务器实例上的远程克隆语句事件;在接收端执行CLONE INSTANCE语句时生成。

欲了解有关监控性能模式语句事件的更多信息,请参见 第 29.12.6 节,“性能模式语句事件表”。

内存工具

性能模式内存工具跟踪内存使用情况。克隆内存使用工具包括:

  • memory/innodb/clone: 跟踪 InnoDB 为动态快照分配的内存。
  • memory/clone/data: 跟踪克隆操作期间克隆插件分配的内存。

欲了解使用性能模式监控内存使用情况的更多信息,请参见 第 29.12.20.10 节,“内存摘要表”。

Com_clone 状态变量

Com_clone 状态变量提供了 CLONE 语句执行次数的计数。

欲了解更多信息,请参考关于 Com_xxx 语句计数变量的讨论,见 第 7.1.10 节,“服务器状态变量”。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-stop.html

7.6.7.11 停止克隆操作

如有必要,您可以使用KILL QUERY *processlist_id*语句停止克隆操作。

在接收端的 MySQL 服务器实例中,您可以从clone_status表的PID列中检索克隆操作的进程列表标识符(PID)。

代码语言:javascript复制
mysql> SELECT * FROM performance_schema.clone_statusG
*************************** 1. row ***************************
             ID: 1
            PID: 8
          STATE: In Progress
     BEGIN_TIME: 2019-07-15 11:58:36.767
       END_TIME: NULL
         SOURCE: LOCAL INSTANCE
    DESTINATION: /*path/to/clone_dir*/
       ERROR_NO: 0
  ERROR_MESSAGE:
    BINLOG_FILE:
BINLOG_POSITION: 0
  GTID_EXECUTED:

您还可以从INFORMATION_SCHEMA PROCESSLIST表的ID列,SHOW PROCESSLIST输出的Id列,或性能模式threads表的PROCESSLIST_ID列中检索进程列表标识符。这些获取 PID 信息的方法可用于捐赠者或接收者的 MySQL 服务器实例。

dev.mysql.com/doc/refman/8.0/en/clone-plugin-option-variable-reference.html

7.6.7.12 克隆系统变量参考

表 7.7 克隆系统变量参考

名称

命令行

选项文件

系统变量

状态变量

变量范围

动态

自动调整并发性

全局

克隆块 DDL

全局

克隆缓冲区大小

全局

DDL 超时

全局

数据丢弃后的延迟

全局

网络故障后的捐赠者超时

全局

启用压缩

全局

最大并发数

全局

最大数据带宽

全局

克隆最大网络带宽

全局

SSL CA

全局

SSL 证书

全局

SSL 密钥

全局

克隆有效捐赠者列表

全局

名称

命令行

选项文件

系统变量

状态变量

变量范围

动态

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-options-variables.html

7.6.7.13 克隆系统变量

本节描述了控制克隆插件操作的系统变量。如果在启动时指定的值不正确,则克隆插件可能无法正确初始化,服务器也不会加载它。在这种情况下,服务器可能还会因为不识别它们而为其��克隆设置产生错误消息。

每个系统变量都有一个默认值。系统变量可以在服务器启动时使用命令行选项或选项文件进行设置。它们可以使用SET语句在运行时动态更改,这使您能够修改服务器的操作而无需停止和重新启动它。

通常,设置全局系统变量的运行时值需要SYSTEM_VARIABLES_ADMIN权限(或已弃用的SUPER权限)。有关更多信息,请参见第 7.1.9.1 节,“系统变量权限”。

克隆变量在执行克隆操作的接收方 MySQL 服务器实例上进行配置。

  • clone_autotune_concurrency 命令行格式--clone-autotune-concurrency引入8.0.17系统变量clone_autotune_concurrency范围全局动态是SET_VAR 提示适用否类型布尔默认值ON当启用clone_autotune_concurrency(默认情况下),为了优化数据传输速度,为远程克隆操作动态生成额外的线程。此设置仅适用于接收方 MySQL 服务器实例。 在克隆操作期间,线程数逐渐增加,直至达到当前线程数的两倍目标。在每个增量评估数据传输速度的影响。根据以下规则,该过程要么继续,要么停止:
    • 如果数据传输速度在增量增加时下降超过 5%,则该过程停止。
    • 如果在达到目标的 25%后有至少 5%的改进,则该过程继续。否则,该过程停止。
    • 如果在达到目标的 50%后有至少 10%的改进,则该过程继续。否则,该过程停止。
    • 如果在达到目标后有至少 25%的改进,则该过程继续,朝着当前线程数的两倍新目标前进。否则,该过程停止。

    自动调整过程不支持减少线程数。 clone_max_concurrency变量定义了可以生成的最大线程数。 如果禁用clone_autotune_concurrencyclone_max_concurrency定义了远程克隆操作生成的线程数。

  • clone_buffer_size 命令行格式--clone-buffer-size引入版本8.0.17系统变量clone_buffer_size作用域全局动态是SET_VAR提示适用否类型整数默认值4194304最小值1048576最大值268435456单位字节定义本地克隆操作期间传输数据时使用的中间缓冲区的大小。默认值为 4 兆字节(MiB)。较大的缓冲区大小可以允许 I/O 设备驱动程序并行获取数据,从而提高克隆性能。
  • clone_block_ddl 命令行格式--clone-block-ddl引入版本8.0.27系统变量clone_block_ddl作用域全局动态是SET_VAR提示适用否类型布尔默认值OFF在克隆操作期间在捐赠者 MySQL 服务器实例上启用独占备份锁,这会阻止捐赠者上的并发 DDL 操作。参见第 7.6.7.4 节,“克隆和并发 DDL”。
  • clone_delay_after_data_drop 命令行格式--clone-delay-after-data-drop引入版本8.0.29系统变量clone_delay_after_data_drop作用域全局动态是SET_VAR提示适用否类型整数默认值0最小值0最大值3600单位字节指定在远程克隆操作开始时,在接收 MySQL 服务器实例上删除现有数据后立即延迟的时间段。延迟旨在在从捐赠者 MySQL 服务器实例克隆数据之前为接收主机上的文件系统释放足够的空间。某些文件系统(如 VxFS)会在后台进程中异步释放空间。在这些文件系统上,在删除现有数据后太快克隆数据可能导致由于空间不足而克隆操作失败。最大延迟时间为 3600 秒(1 小时)。默认设置为 0(无延迟)。 此变量仅适用于远程克隆操作,并配置在接收 MySQL 服务器实例上。
  • clone_ddl_timeout 命令行格式--clone-ddl-timeout引入版本8.0.17系统变量clone_ddl_timeout范围全局动态是SET_VAR提示适用否类型整数默认值300最小值0最大值2592000单位秒克隆操作等待备份锁的时间(以秒为单位)。备份锁在执行克隆操作时阻止并发 DDL。此设置应用于捐赠者和接收者 MySQL 服务器实例。 设置为 0 意味着克隆操作不会等待备份锁。在这种情况下,执行并发的 DDL 操作可能会导致克隆操作失败。 在 MySQL 8.0.27 之前,在克隆操作期间,备份锁会阻止捐赠者和接收者上的并发 DDL 操作,并且在当前 DDL 操作完成之前,克隆操作无法继续进行。从 MySQL 8.0.27 开始,如果clone_block_ddl变量设置为OFF(默认值),则在克隆操作期间允许在捐赠者上进行并发 DDL 操作。在这种情况下,克隆操作不必等待捐赠者上的备份锁。参见第 7.6.7.4 节,“克隆和并发 DDL”。
  • clone_donor_timeout_after_network_failure 命令行格式--clone-donor-timeout-after-network-failure引入版本8.0.24系统变量clone_donor_timeout_after_network_failure范围全局动态是SET_VAR提示适用否类型整数默认值5最小值0最大值30单位分钟定义了在网络故障后,捐赠方允许接收方重新连接并重新启动克隆操作的时间长度(以分钟为单位)。更多信息请参见第 7.6.7.9 节,“远程克隆操作失败处理”。 此变量设置在捐赠 MySQL 服务器实例上。在接收 MySQL 服务器实例上设置它没有任何效果。
  • clone_enable_compression 命令行格式--clone-enable-compression引入版本8.0.17系统变量clone_enable_compression范围全局动态是SET_VAR 提示适用否类型布尔默认值OFF启用在远程克隆操作期间在网络层对数据进行压缩。压缩可以节省网络带宽,但会消耗 CPU。启用压缩可能会提高数据传输速率。此设置仅应用于接收 MySQL 服务器实例。
  • clone_max_concurrency 命令行格式--clone-max-concurrency引入版本8.0.17系统变量clone_max_concurrency范围全局动态是SET_VAR 提示适用否类型整数默认值16最小值1最大值128单位线程定义了远程克隆操作的最大并发线程数。默认值为 16。更多的线程数可以提高克隆性能,但也会减少允许的同时客户端连接数,这可能会影响现有客户端连接的性能。此设置仅应用于接收 MySQL 服务器实例。 如果启用了clone_autotune_concurrency(默认情况下),clone_max_concurrency是可以为远程克隆操作动态生成的最大线程数。如果禁用了clone_autotune_concurrencyclone_max_concurrency定义了为远程克隆操作生成的线程数。 推荐远程克隆操作每个线程的最小数据传输速率为 1 Mebibyte(MiB)每秒。远程克隆操作的数据传输速率由 clone_max_data_bandwidth 变量控制。
  • clone_max_data_bandwidth 命令行格式--clone-max-data-bandwidth引入版本8.0.17系统变量clone_max_data_bandwidth作用范围全局动态是SET_VAR Hint Applies否类型整数默认值0最小值0最大值1048576单位MiB/秒定义了远程克隆操作每秒的最大数据传输速率(以 Mebibytes(MiB)为单位)。此变量有助于管理克隆操作的性能影响。仅当捐赠端磁盘 I/O 带宽饱和,影响性能时,才应设置限制。值为 0 表示“无限制”,允许克隆操作以最高可能的数据传输速率运行。此设置仅适用于接收端 MySQL 服务器实例。 每个线程的最小数据传输速率为每秒 1 MiB。例如,如果有 8 个线程,则最小传输速率为每秒 8 MiB。clone_max_concurrency 变量控制了远程克隆操作生成的最大线程数。 由 clone_max_data_bandwidth 指定的请求数据传输速率可能与 performance_schema.clone_progress 表中的 DATA_SPEED 列报告的实际数据传输速率不同。如果您的克隆操作未达到所需的数据传输速率,并且有可用带宽,请检查接收端和捐赠端的 I/O 使用情况。如果有未充分利用的带宽,则 I/O 是下一个最可能成为瓶颈的地方。
  • clone_max_network_bandwidth 命令行格式--clone-max-network-bandwidth引入版本8.0.17系统变量clone_max_network_bandwidth作用范围全局动态是SET_VAR Hint Applies否类型整数默认值0最小值0最大值1048576单位MiB/秒指定远程克隆操作每秒的最大近似网络传输速率(以 mebibytes(MiB)为单位)。此变量可用于管理克隆操作对网络带宽的性能影响。仅当网络带宽饱和,影响捐赠��实例上的性能时才应设置该值。值为 0 表示“无限制”,允许以网络上最高可能的数据传输速率进行克隆,提供最佳性能。此设置仅适用于接收端 MySQL 服务器实例。
  • clone_ssl_ca 命令行格式--clone-ssl-ca=file_name引入版本8.0.14系统变量clone_ssl_ca作用范围全局动态是SET_VAR 提示适用否类型文件名默认值空字符串指定证书颁发机构(CA)文件的路径。用于配置远程克隆操作的加密连接。此设置在接收端配置,并在连接到捐赠者时使用。
  • clone_ssl_cert 命令行格式--clone-ssl-cert=file_name引入版本8.0.14系统变量clone_ssl_cert作用范围全局动态是SET_VAR 提示适用否类型文件名默认值空字符串指定公钥证书的路径。用于配置远程克隆操作的加密连接。此设置在接收端配置,并在连接到捐赠者时使用。
  • clone_ssl_key 命令行格式--clone-ssl-key=file_name引入版本8.0.14系统变量clone_ssl_key作用范围全局动态是SET_VAR 提示适用否类型文件名默认值空字符串指定私钥文件的路径。用于配置远程克隆操作的加密连接。此设置在接收端配置,并在连接到捐赠者时使用。
  • clone_valid_donor_list 命令行格式--clone-valid-donor-list=value引入版本8.0.17系统变量clone_valid_donor_list作用范围全局动态是SET_VAR 提示适用否类型字符串默认值NULL定义远程克隆操作的有效捐赠主机地址。此设置应用于接收方 MySQL 服务器实例。允许以逗号分隔的值列表,格式如下:“HOST1:PORT1,HOST2:PORT2,HOST3:PORT3”。不允许有空格。 clone_valid_donor_list变量通过控制克隆数据源提供了一层安全性。配置clone_valid_donor_list所需的权限与执行远程克隆操作所需的权限不同,这允许将这些责任分配给不同的角色。配置clone_valid_donor_list需要SYSTEM_VARIABLES_ADMIN权限,而执行远程克隆操作需要CLONE_ADMIN权限。 不支持 Internet Protocol version 6 (IPv6)地址格式。可以使用 IPv6 地址的别名。IPv4 地址可以直接使用。

原文:dev.mysql.com/doc/refman/8.0/en/clone-plugin-limitations.html

7.6.7.14 克隆插件限制

克隆插件受到以下限制:

  • 无法从不同的 MySQL 服务器系列克隆实例。例如,您不能在 MySQL 8.0 和 MySQL 8.4 之间克隆,但可以在同一系列内克隆,例如 MySQL 8.0.37 和 MySQL 8.0.42。在 8.0.37 之前,点发布号也必须匹配,因此不允许克隆类似于 8.0.36 到 8.0.42 或反之亦然。
  • 在 MySQL 8.0.27 之前,在克隆操作期间不允许在捐赠者和接收者上进行 DDL,包括TRUNCATE TABLE。在选择数据源时应考虑此限制。一种解决方法是使用专用的捐赠者实例,在克隆数据时可以阻止 DDL 操作。允许并发 DML。 从 MySQL 8.0.27 开始,默认情况下允许在捐赠者上进行并发 DDL。对于捐赠者上的并发 DDL 的支持由clone_block_ddl变量控制。请参见第 7.6.7.4 节,“克隆和并发 DDL”。
  • 仅在 MySQL 8.0.26 及更高版本中支持从捐赠者 MySQL 服务器实例克隆到相同版本和发布的热修复 MySQL 服务器实例。
  • 一次只能克隆一个 MySQL 实例。不支持在单个克隆操作中克隆多个 MySQL 实例。
  • 未支持远程克隆操作(在CLONE INSTANCE语句中指定捐赠者 MySQL 服务器实例的端口号时)的mysqlx_port指定的 X 协议端口。
  • 克隆插件不支持克隆 MySQL 服务器配置。接收方 MySQL 服务器实例保留其配置,包括持久化的系统变量设置(参见第 7.1.9.3 节,“持久化系统变量”)。
  • 克隆插件不支持克隆二进制日志。
  • 克隆插件仅克隆存储在InnoDB中的数据。不会克隆其他存储引擎的数据。存储在任何模式中的MyISAMCSV表将被克隆为空表。
  • 通过 MySQL 路由器连接到捐赠者 MySQL 服务器实例不受支持。
  • 本地克隆操作不支持使用绝对路径创建的通用表空间的克隆。克隆的表空间文件与源表空间文件具有相同路径会引起冲突。

7.6.8 密钥环代理桥插件

原文:dev.mysql.com/doc/refman/8.0/en/daemon-keyring-proxy-plugin.html

MySQL Keyring 最初使用服务器插件实现了密钥库功能,但从 MySQL 8.0.24 开始开始过渡到使用组件基础架构。 过渡包括修改密钥环插件的底层实现以使用组件基础架构。 这是通过名为daemon_keyring_proxy_plugin的插件实现的,它充当插件和组件服务 API 之间的桥梁,并使密钥环插件可以继续使用而不会改变用户可见的特性。

daemon_keyring_proxy_plugin是内置的,无需安装或启用。

7.6.9 MySQL 插件服务

原文:dev.mysql.com/doc/refman/8.0/en/plugin-services.html

7.6.9.1 锁定服务

7.6.9.2 密钥环服务

MySQL 服务器插件可以访问服务器的“插件服务”。插件服务接口通过暴露插件可以调用的服务器功能来补充插件 API。有关编写插件服务的开发人员信息,请参阅 MySQL 插件服务。以下部分描述了在 SQL 和 C 语言级别可用的插件服务。

原文:dev.mysql.com/doc/refman/8.0/en/locking-service.html

7.6.9.1 锁定服务

MySQL 发行版提供了一个可在两个级别访问的锁定接口:

  • 在 SQL 级别上,作为一组可加载函数,每个函数映射到对服务例程的调用。
  • 作为 C 语言接口,可作为服务器插件或可加载函数的插件服务调用。

有关插件服务的一般信息,请参见 Section 7.6.9, “MySQL Plugin Services”。有关可加载函数的一般信息,请参见添加可加载函数。

锁定接口具有以下特点:

  • 锁具有三个属性:锁命名空间、锁名称和锁模式:
    • 锁由命名空间和锁名称的组合标识。命名空间使不同应用程序可以在不发生冲突的情况下使用相同的锁名称,方法是在不同的命名空间中创建锁。例如,如果应用程序 A 和 B 使用命名空间ns1ns2,则每个应用程序可以使用锁名称lock1lock2而不会干扰另一个应用程序。
    • 锁模式为读或写。读锁是共享的:如果一个会话对给定的锁标识符有读锁定,则其他会话可以对相同标识符获取读锁定。写锁是排他的:如果一个会话对给定的锁标识符有写锁定,则其他会话无法对相同标识符获取读或写锁定。
  • 命名空间和锁名称必须为非NULL、非空,并且最大长度为 64 个字符。如果命名空间或锁名称指定为NULL、空字符串或长度超过 64 个字符,则会导致ER_LOCKING_SERVICE_WRONG_NAME错误。
  • 锁定接口将命名空间和锁名称视为二进制字符串,因此比较区分大小写。
  • 锁定接口提供了获取锁定和释放锁定的函数。调用这些函数不需要特殊权限。权限检查是调用应用程序的责任。
  • 如果锁定不可立即获得,可以等待锁定。锁定获取调用需要一个整数超时值,指示在放弃之前等待多少秒以获取锁定。如果超时到达而未成功获取锁定,则会发生ER_LOCKING_SERVICE_TIMEOUT错误。如果超时为 0,则不会等待,如果无法立即获取锁定,则调用会产生错误。
  • 锁定接口检测不同会话中的锁获取调用之间的死锁。在这种情况下,锁定服务选择一个调用者,并以ER_LOCKING_SERVICE_DEADLOCK错误终止其锁获取请求。此错误不会导致事务回滚。在死锁情况下选择会话时,锁定服务更喜欢持有读锁的会话而不是持有写锁的会话。
  • 一个会话可以通过单个锁获取调用获取多个锁。对于给定的调用,锁获取是原子的:如果所有锁都被获取,则调用成功。如果任何锁的获取失败,则调用不会获取任何锁并失败,通常会出现ER_LOCKING_SERVICE_TIMEOUTER_LOCKING_SERVICE_DEADLOCK错误。
  • 一个会话可以为相同的锁标识符(命名空间和锁名称组合)获取多个锁。这些锁实例可以是读锁、写锁或两者的混合。
  • 在会话中获取的锁通过显式调用释放锁函数释放,或者在会话正常或异常终止时隐式释放。当事务提交或回滚时不会释放锁。
  • 在一个会话中,释放给定命名空间的所有锁时会一起释放。

锁定服务提供的接口与GET_LOCK()及相关 SQL 函数提供的接口不同(请参见第 14.14 节,“锁定函数”)。例如,GET_LOCK()不实现命名空间,并且仅提供排他锁,而不是不同的读锁和写锁。

7.6.9.1.1 锁定服务 C 接口

本节描述如何使用锁定服务的 C 语言接口。要使用函数接口,请参见第 7.6.9.1.2 节,“锁定服务函数接口”有关锁定服务接口的一般特性,请参见第 7.6.9.1 节,“锁定服务”有关插件服务的一般信息,请参见第 7.6.9 节,“MySQL 插件服务”。

使用锁定服务的源文件应包含此头文件:

代码语言:javascript复制
#include <mysql/service_locking.h>

要获取一个或多个锁,请调用此函数:

代码语言:javascript复制
int mysql_acquire_locking_service_locks(MYSQL_THD opaque_thd,
                                        const char* lock_namespace,
                                        const char**lock_names,
                                        size_t lock_num,
                                        enum enum_locking_service_lock_type lock_type,
                                        unsigned long lock_timeout);

参数的含义如下:

  • opaque_thd: 一个线程句柄。如果指定为NULL,则使用当前线程的句柄。
  • lock_namespace: 一个以空字符结尾的字符串,表示锁命名空间。
  • lock_names: 一个以空字符结尾的字符串数组,提供要获取的锁的名称。
  • lock_num: lock_names数组中名称的数量。
  • lock_type: 锁定模式,可以是LOCKING_SERVICE_READLOCKING_SERVICE_WRITE,分别用于获取读锁或写锁。
  • lock_timeout: 等待获取锁的秒数,超时放弃。

要释放为给定命名空间获取的锁,请调用此函数:

代码语言:javascript复制
int mysql_release_locking_service_locks(MYSQL_THD opaque_thd,
                                        const char* lock_namespace);

参数的含义如下:

  • opaque_thd: 一个线程句柄。如果指定为NULL,则使用当前线程的句柄。
  • lock_namespace: 一个以空字符结尾的字符串,表示锁定命名空间。

通过性能模式可以在 SQL 级别监视由锁定服务获取或等待的锁。详情请参见锁定服务监视。

7.6.9.1.2 锁定服务函数接口

本节描述了如何使用其可加载函数提供的锁定服务接口。要使用 C 语言接口,请参见 Section 7.6.9.1.1, “锁定服务 C 接口”。有关锁定服务接口的一般特性,请参见 Section 7.6.9.1, “锁定服务”。有关可加载函数的一般信息,请参见添加可加载函数。

  • 安装或卸载锁定服务函数接口
  • 使用锁定服务函数接口
  • 锁定服务监视
  • 锁定服务接口函数参考
安装或卸载锁定服务函数接口

描述在 Section 7.6.9.1.1, “锁定服务 C 接口”中的锁定服务例程不需要安装,因为它们已经内置在服务器中。但映射到服务例程调用的可加载函数不是这样的:这些函数必须在使用之前安装。本节描述了如何进行安装。有关可加载函数安装的一般信息,请参见 Section 7.7.1, “安装和卸载可加载函数”。

锁定服务函数实现在一个插件库文件中,该文件位于由plugin_dir系统变量命名的目录中。文件基本名称为locking_service。文件名后缀因平台而异(例如,Unix 和类 Unix 系统为.so,Windows 为.dll)。

要安装锁定服务函数,请使用CREATE FUNCTION语句,并根据需要调整.so后缀以适配您的平台:

代码语言:javascript复制
CREATE FUNCTION service_get_read_locks RETURNS INT
  SONAME 'locking_service.so';
CREATE FUNCTION service_get_write_locks RETURNS INT
  SONAME 'locking_service.so';
CREATE FUNCTION service_release_locks RETURNS INT
  SONAME 'locking_service.so';

如果在复制源服务器上使用这些函数,请在所有副本服务器上安装它们,以避免复制问题。

一旦安装,函数将一直保持安装状态,直到卸载。要删除它们,请使用DROP FUNCTION语句:

代码语言:javascript复制
DROP FUNCTION service_get_read_locks;
DROP FUNCTION service_get_write_locks;
DROP FUNCTION service_release_locks;
使用锁定服务函数接口

在使用锁定服务函数之前,请根据提供的说明安装它们,详情请参阅安装或卸载锁定服务函数接口。

要获取一个或多个读锁,请调用此函数:

代码语言:javascript复制
mysql> SELECT service_get_read_locks('mynamespace', 'rlock1', 'rlock2', 10);
 --------------------------------------------------------------- 
| service_get_read_locks('mynamespace', 'rlock1', 'rlock2', 10) |
 --------------------------------------------------------------- 
|                                                             1 |
 --------------------------------------------------------------- 

第一个参数是锁定命名空间。最后一个参数是一个整数超时,指示在放弃之前等待多少秒才能获取锁。中间的参数是锁定名称。

对于刚刚显示的示例,该函数获取具有锁定标识符(mynamespace, rlock1)(mynamespace, rlock2)的锁。

要获取写锁而不是读锁,请调用此函数:

代码语言:javascript复制
mysql> SELECT service_get_write_locks('mynamespace', 'wlock1', 'wlock2', 10);
 ---------------------------------------------------------------- 
| service_get_write_locks('mynamespace', 'wlock1', 'wlock2', 10) |
 ---------------------------------------------------------------- 
|                                                              1 |
 ---------------------------------------------------------------- 

在这种情况下,锁定标识符为(mynamespace, wlock1)(mynamespace, wlock2)

要释放命名空间的所有锁,请使用此函数:

代码语言:javascript复制
mysql> SELECT service_release_locks('mynamespace');
 -------------------------------------- 
| service_release_locks('mynamespace') |
 -------------------------------------- 
|                                    1 |
 -------------------------------------- 

每个锁定函数成功返回非零值。如果函数失败,将会发生错误。例如,由于锁定名称不能为空,会发生以下错误:

代码语言:javascript复制
mysql> SELECT service_get_read_locks('mynamespace', '', 10);
ERROR 3131 (42000): Incorrect locking service lock name ''.

一个会话可以为相同的锁标识符获取多个锁。只要不同会话没有对标识符的写锁,该会话可以获取任意数量的读锁或写锁。对于标识符的每个锁请求都会获取一个新锁。以下语句获取具有相同标识符的三个写锁,然后获取相同标识符的三个读锁:

代码语言:javascript复制
SELECT service_get_write_locks('ns', 'lock1', 'lock1', 'lock1', 0);
SELECT service_get_read_locks('ns', 'lock1', 'lock1', 'lock1', 0);

如果此时检查性能模式metadata_locks表,您应该发现会话持有六个具有相同(ns, lock1)标识符的不同锁。(详情请参阅锁定服务监控。)

因为会话至少持有一个对(ns, lock1)的写锁,其他会话无法为其获取读锁或写锁。如果会话仅持有标识符的读锁,其他会话可以获取其读锁,但无法获取写锁。

单个锁获取调用的锁是原子获取的,但原子性不适用于跨调用。因此,对于以下语句,其中每行结果集调用一次 service_get_write_locks(),每个单独调用的原子性保持,但对于整个语句不保持:

代码语言:javascript复制
SELECT service_get_write_locks('ns', 'lock1', 'lock2', 0) FROM t1 WHERE ... ;

注意

因为锁定服务为给定锁标识符的每个成功请求返回一个单独的锁,所以一个语句可能获取大量锁。例如:

代码语言:javascript复制
INSERT INTO ... SELECT service_get_write_locks('ns', t1.col_name, 0) FROM t1;

这些类型的语句可能会产生某些不良影响。例如,如果语句在中途失败并回滚,则在失败点之前获取的锁仍然存在。如果意图是要求插入的行与获取的锁对应,那么这个意图就无法实现。此外,如果重要的是按照特定顺序授予锁,请注意结果集顺序可能会因优化器选择的执行计划而有所不同。因此,最好限制每个语句对单个锁获取调用。

锁定服务监控

锁定服务是使用 MySQL Server 元数据锁框架实现的,因此您可以通过检查性能模式 metadata_locks 表来监视锁定服务获取或等待的锁。

首先,启用元数据锁仪器:

代码语言:javascript复制
mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES'
 -> WHERE NAME = 'wait/lock/metadata/sql/mdl';

然后获取一些锁并检查 metadata_locks 表的内容:

代码语言:javascript复制
mysql> SELECT service_get_write_locks('mynamespace', 'lock1', 0);
 ---------------------------------------------------- 
| service_get_write_locks('mynamespace', 'lock1', 0) |
 ---------------------------------------------------- 
|                                                  1 |
 ---------------------------------------------------- 
mysql> SELECT service_get_read_locks('mynamespace', 'lock2', 0);
 --------------------------------------------------- 
| service_get_read_locks('mynamespace', 'lock2', 0) |
 --------------------------------------------------- 
|                                                 1 |
 --------------------------------------------------- 
mysql> SELECT OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_STATUS
 -> FROM performance_schema.metadata_locks
 -> WHERE OBJECT_TYPE = 'LOCKING SERVICE'G
*************************** 1. row ***************************
  OBJECT_TYPE: LOCKING SERVICE
OBJECT_SCHEMA: mynamespace
  OBJECT_NAME: lock1
    LOCK_TYPE: EXCLUSIVE
  LOCK_STATUS: GRANTED
*************************** 2. row ***************************
  OBJECT_TYPE: LOCKING SERVICE
OBJECT_SCHEMA: mynamespace
  OBJECT_NAME: lock2
    LOCK_TYPE: SHARED
  LOCK_STATUS: GRANTED

锁定服务锁的 OBJECT_TYPE 值为 LOCKING SERVICE。这与例如使用 GET_LOCK() 函数获取的锁不同,后者的 OBJECT_TYPEUSER LEVEL LOCK

锁定命名空间、名称和模式出现在 OBJECT_SCHEMAOBJECT_NAMELOCK_TYPE 列中。读取和写入锁的 LOCK_TYPE 值分别为 SHAREDEXCLUSIVE

LOCK_STATUS 值为 GRANTED 表示已获取锁,PENDING 表示正在等待锁。如果一个会话持有写锁,另一个会话正在尝试获取具有相同标识符的锁,则可以期望看到 PENDING

锁定服务接口函数参考

锁定服务的 SQL 接口实现了本节中描述的可加载函数。有关使用示例,请参见 使用锁定服务函数接口。

这些函数具有以下特征:

  • 返回值为非零表示成功。否则,将发生错误。
  • 命名空间和锁名称必须为非NULL、非空,并且最大长度为 64 个字符。
  • 超时值必须是整数,表示在放弃并产生错误之前等待获取锁的秒数。如果超时为 0,则不会等待,如果无法立即获取锁,则函数会产生错误。

这些锁定服务函数可用:

  • service_get_read_locks(*namespace*, *lock_name*[, *lock_name*] ..., *timeout*) 使用给定的锁名称在给定的命名空间中获取一个或多个读(共享)锁,在给定的超时值内未获取到锁时会超时报错。
  • service_get_write_locks(*namespace*, *lock_name*[, *lock_name*] ..., *timeout*) 使用给定的锁名称在给定的命名空间中获取一个或多个写(独占)锁,在给定的超时值内未获取到锁时会超时报错。
  • service_release_locks(*namespace*) 对于给定的命名空间,释放当前会话中使用service_get_read_locks()service_get_write_locks()获取的所有锁。 在命名空间中没有锁也不是错误。 ------------------------------------------- | 1 | ±--------------------------------------------------- mysql> SELECT service_get_read_locks(‘mynamespace’, ‘lock2’, 0); ±-------------------------------------------------- | service_get_read_locks(‘mynamespace’, ‘lock2’, 0) | ±-------------------------------------------------- | 1 | ±-------------------------------------------------- mysql> SELECT OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_STATUS -> FROM performance_schema.metadata_locks -> WHERE OBJECT_TYPE = ‘LOCKING SERVICE’G *************************** 1. row *************************** OBJECT_TYPE: LOCKING SERVICE OBJECT_SCHEMA: mynamespace OBJECT_NAME: lock1 LOCK_TYPE: EXCLUSIVE LOCK_STATUS: GRANTED *************************** 2. row *************************** OBJECT_TYPE: LOCKING SERVICE OBJECT_SCHEMA: mynamespace OBJECT_NAME: lock2 LOCK_TYPE: SHARED LOCK_STATUS: GRANTED
代码语言:javascript复制
锁定服务锁的 `OBJECT_TYPE` 值为 `LOCKING SERVICE`。这与例如使用 `GET_LOCK()` 函数获取的锁不同,后者的 `OBJECT_TYPE` 为 `USER LEVEL LOCK`。

锁定命名空间、名称和模式出现在 `OBJECT_SCHEMA`、`OBJECT_NAME` 和 `LOCK_TYPE` 列中。读取和写入锁的 `LOCK_TYPE` 值分别为 `SHARED` 和 `EXCLUSIVE`。

`LOCK_STATUS` 值为 `GRANTED` 表示已获取锁,`PENDING` 表示正在等待锁。如果一个会话持有写锁,另一个会话正在尝试获取具有相同标识符的锁,则可以期望看到 `PENDING`。

###### 锁定服务接口函数参考

锁定服务的 SQL 接口实现了本节中描述的可加载函数。有关使用示例,请参见 使用锁定服务函数接口。

这些函数具有以下特征:

    返回值为非零表示成功。否则,将发生错误。

    命名空间和锁名称必须为非`NULL`、非空,并且最大长度为 64 个字符。

    超时值必须是整数,表示在放弃并产生错误之前等待获取锁的秒数。如果超时为 0,则不会等待,如果无法立即获取锁,则函数会产生错误。

这些锁定服务函数可用:

    [`service_get_read_locks(*`namespace`*, *`lock_name`*[, *`lock_name`*] ..., *`timeout`*)`](locking-service.html#function_service-get-read-locks)

    使用给定的锁名称在给定的命名空间中获取一个或多个读(共享)锁,在给定的超时值内未获取到锁时会超时报错。

    [`service_get_write_locks(*`namespace`*, *`lock_name`*[, *`lock_name`*] ..., *`timeout`*)`](locking-service.html#function_service-get-write-locks)

    使用给定的锁名称在给定的命名空间中获取一个或多个写(独占)锁,在给定的超时值内未获取到锁时会超时报错。

    `service_release_locks(*`namespace`*)`

    对于给定的命名空间,释放当前会话中使用`service_get_read_locks()`和`service_get_write_locks()`获取的所有锁。

    在命名空间中没有锁也不是错误。

0 人点赞