MySQL8 中文参考(七十六)(mysql8.0中文文档)

MySQL8 中文参考(七十六) 原文:docs.oracle.com/javase/tutorial/reallybigindex.html 18.6 BLACKHOLE 存储引擎 原文:dev.mysql.c

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

18.6 BLACKHOLE 存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/blackhole-storage-engine.html

BLACKHOLE存储引擎充当“黑洞”,接受数据但丢弃它而不存储它。搜索总是返回空结果。

mysql 创建表测试(i INT, c CHAR(10)) ENGINE=BLACKHOLE;

查询正常,0 行受影响(0.03 秒)

mysql INSERT INTO test VALUES(1,\’记录1\’),(2,\’记录2\’);

查询正常,2 行受影响(0.00 秒)

记录: 2 重复: 0 警告: 0

mysql SELECT * FROM 测试;

空集(0.00 秒)

如果您从源代码构建MySQL 并希望启用BLACKHOLE 存储引擎,请使用-DWITH_BLACKHOLE_STORAGE_ENGINE 选项调用CMake。

要查看BLACKHOLE 引擎的源代码,请查看MySQL 源代码分发版的sql 目录。

创建BLACKHOLE 表时,服务器会在全局数据字典中创建表定义。与表关联的文件不存在。

BLACKHOLE存储引擎支持不同类型的索引。也就是说,您可以在表定义中包含索引声明。

从MySQL 8.0.27 开始,最大密钥长度为3072 字节。在8.0.27 之前,最大密钥长度为1000 字节。

BLACKHOLE存储引擎不支持分区。

您可以使用SHOW ENGINES语句检查BLACKHOLE存储引擎是否可用。

向BLACKHOLE 表中插入不会保存任何数据,但如果启用基于语句的二进制日志记录,则会记录SQL 语句并将其复制到副本服务器。这充当中继器或过滤器机制。

假设您的应用程序需要副本端过滤规则,但首先将所有二进制日志数据转发到副本会产生过多的流量。在这种情况下,您可以在复制源服务器上使用默认存储引擎BLACKHOLE 设置“虚拟”复制进程,如下所示:

图18.1 使用BLACKHOLE 过滤复制

源服务器写入二进制日志。 “虚拟”mysqld 进程充当副本,应用必要的replicate-do-* 和replicate-ignore-* 规则并编写自己的新过滤二进制日志。 (请参见第19.1.6 节“复制和二进制日志选项和变量”。)此过滤日志将提供给副本。

由于虚拟进程实际上并不存储数据,因此在复制源服务器上运行额外的mysqld 进程时,处理开销很小。可以通过添加额外的副本来重复此配置。

BLACKHOLE 表上的INSERT 触发器按预期工作。但是,BLACKHOLE 表实际上并不存储任何数据,因此UPDATE 和DELETE 触发器不会被激活。由于没有行,因此触发器定义中的FOR EACH ROW 子句不适用。

BLACKHOLE 存储引擎的其他可能用途包括:

检查转储文件的语法。

通过比较启用和禁用二进制日志记录的情况下使用BLACKHOLE 的性能来衡量二进制日志记录的开销。

因为BLACKHOLE本质上是一个“无操作”的存储引擎,所以它可以用来发现与存储引擎本身无关的性能瓶颈。

BLACKHOLE 引擎是事务感知的。也就是说,已提交的事务会写入二进制日志,但回滚的事务不会写入二进制日志。

黑洞引擎和自动增量列

BLACKHOLE 发动机是一种不运转的发动机。使用BLACKHOLE 对表执行的操作没有效果。在考虑自动增量主键列的行为时请记住这一点。引擎不会自动递增字段值,也不保留自动递增字段的状态。这对于复制具有重要意义。

考虑以下所有三个条件都成立的复制场景:

源服务器有一个黑洞表,其中一个自动增量字段是主键。

副本上存在相同的表,但使用MyISAM 引擎。

通过在INSERT 语句本身中显式设置自动增量值或使用SET INSERT_ID 语句将数据插入到源表中。

在这种情况下,复制会由于主键列中的重复条目错误而失败。

在基于语句的复制中,上下文事件的INSERT_ID 值始终相同。因此,如果尝试在主键列中插入具有重复值的行,复制将会失败。

在基于行的复制中,每次插入时引擎返回的行值始终相同。这会导致复制失败,因为副本尝试重播主键列中具有相同值的两个插入日志条目。

柱过滤器

使用基于行的复制(binlog_format=ROW) 时,支持缺少表最后一列的副本,如源和副本上具有不同表定义的复制中所述。

此过滤是在副本端执行的。也就是说,列在过滤之前被复制到副本。至少在两种情况下您不希望将列复制到副本。

如果数据敏感,副本服务器不应访问它。

如果源有多个副本,在发送到副本之前进行过滤可以减少网络流量。

源列过滤可以使用BLACKHOLE 引擎来实现。这是通过与源表过滤类似的方式实现的(使用BLACKHOLE 引擎和–replicate-do-table 或–replicate-ignore-table 选项)。

源设置为:

创建表t1 (public_col_1, public_col_N,

Secret_col_1, Secret_col_M) ENGINE=MyISAM;

可信副本设置如下:

创建表t1 (public_col_1, public_col_N) ENGINE=BLACKHOLE;

不可信副本设置如下:

创建表t1 (public_col_1, public_col_N) ENGINE=MyISAM;

18.7 MERGE 存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/merge-storage-engine.html

18.7.1 MERGE 表的优点和缺点

18.7.2 MERGE 表问题

MERGE存储引擎,也称为MRG_MyISAM引擎,是一组相同的MyISAM表,可以作为一个整体使用。 “相同”是指所有表具有相同的列数据类型和索引信息。如果列的排列顺序不同、相应列的数据类型不完全相同或者索引的顺序不同,则无法合并MyISAM 表。但是,部分或全部MyISAM 表可以使用myisampack 进行压缩。请参阅myisampack — 生成压缩的只读MyISAM 表。这些表之间的差异并不显着。

对应的列名和索引名可能不同。

表、列和索引的注释可能会有所不同。

AVG_ROW_LENGTH、MAX_ROWS 和PACK_KEYS 等表选项可能会有所不同。

MERGE 表的替代方案是分区表。它将单个表的分区存储在单独的文件中,使某些操作更加高效。有关详细信息,请参阅第26 章“分区”。

当您创建MERGE 表时,MySQL 在磁盘上创建一个.MRG 文件,其中包含要用作.MRG 文件的基础MyISAM 表的名称。 MERGE 表的表格格式存储在MySQL 数据字典中。基础表不需要与MERGE 表位于同一数据库中。

您可以在MERGE 表上使用SELECT、DELETE、UPDATE 和INSERT。需要对映射到MERGE 表的MyISAM 表具有SELECT、DELETE 和UPDATE 权限。

消息

使用MERGE 表会带来以下安全问题: 如果用户有权访问MyISAM表*t,则该用户可以创建访问t的MERGE表m。然而,即使用户对t的权限随后被撤销,用户仍然可以通过m访问t*。

要仅删除MERGE 规范,请在MERGE 表上使用DROP TABLE。基础表不受影响。

要创建MERGE 表,必须指定UNION=(*table list*) 选项,该选项指示要使用哪个MyISAM 表。您还可以选择指定INSERT_METHOD 选项来控制如何执行向MERGE 表的插入。使用FIRST 或LAST 值插入到第一个或最后一个基础表中。如果未指定INSERT_METHOD 选项或指定为NO,则不允许将数据插入到MERGE 表中,并且尝试这样做时会发生错误。

以下示例显示如何创建MERGE 表。

mysql 创建表t1 (

– INT NOT NULL AUTO_INCRMENT 主键,

– 消息CHAR(20)) ENGINE=MyISAM;

mysql 创建表t2 (

– INT NOT NULL AUTO_INCRMENT 主键,

– 消息CHAR(20)) ENGINE=MyISAM;

mysql INSERT INTO t1 (消息) VALUES (\’测试\’),(\’表\’),(\’t1\’);

mysql INSERT INTO t2 (消息) VALUES (\’测试\’),(\’表\’),(\’t2\’);

mysql CREATE TABLE 总计(

– INT NOT NULL 自动增量,

– 消息CHAR(20)、INDEX(a))

– 引擎=合并联合=(t1,t2) INSERT_METHOD=最后;

列a 在基础MyISAM 表中被索引为PRIMARY KEY,但在MERGE 表中未被索引。该索引存在,但它不作为PRIMARY KEY 存在,因为MERGE 表无法强制基础表的唯一性。 (同样,在基础表上具有UNIQUE 索引的列应在MERGE 表中建立索引,而不是作为UNIQUE 索引。)

创建MERGE 表后,您可以使用它来查询整个表组。

mysql SELECT * FROM 总计;

+—+——–+

| 留言|

+—+——–+

| 测试|

| 2 | 表

| 3 |

| 1 | 测试

| 2 | 表

| 3 |

+—+——–+

要将MERGE 表重新映射到另一个MyISAM 表集合,可以使用以下方法之一:

DROP 并重新创建MERGE 表。

使用ALTER TABLE *tbl_name* UNION=(.) 更改基础表的列表。

您还可以使用ALTER TABLE . UNION=() (即使用空UNION 子句)删除所有基础表。但是,在这种情况下,插入操作将失败,因为表实际上是空的,并且没有基础表来接收新行。这样的表可以用作使用CREATE TABLE . LIKE 创建新MERGE 表的模板。

基础表定义和索引必须与MERGE 表定义完全匹配。当打开属于MERGE 表一部分的表时(而不是创建MERGE 表时)检查合规性。如果任何表未通过合规性检查,则触发打开该表的操作将失败。这意味着使用MERGE 更改表的定义可能会导致访问MERGE 表时出现错误。适用于每个表的合规性检查包括:

基础表和MERGE 表必须具有相同的列数。

基础表和MERGE 表中的列顺序必须匹配。

此外,还会比较父MERGE 表和基础表中每个对应列的规格,并且必须满足以下检查:

基础表和MERGE 表中的列类型必须相同。

基础表和MERGE 表中的列长度必须相等。

基础表和MERGE 表中的列可以为NULL。

基础表必须至少具有与MERGE 表一样多的索引。基础表的索引可能多于MERGE 表,但绝不会少于MERGE 表。

消息

有一个已知问题,即MERGE 表和基础MyISAM 表中相同列上的索引必须具有相同的顺序。请参阅错误#33653。

每个索引必须满足以下检查:

基表和MERGE表必须具有相同的索引类型。

索引定义中索引部分(即复合索引中的多个列)的数量在基表和MERGE 表中必须相同。

对于每个索引部分:

索引部分必须具有相同的长度。

索引部分必须是同一类型。

索引部分的语言必须相同。

请检查索引部分是否可以为NULL。

如果由于基础表的问题而无法打开或使用MERGE 表,CHECK TABLE 将显示有关导致问题的表的信息。

其他资源

专门讨论MERGE 存储引擎的论坛位于forums.mysql.com/list.php?93。

18.7.1 MERGE 表的优缺点

原文:dev.mysql.com/doc/refman/8.0/en/merge-table-advantages.html

MERGE 表有助于解决以下问题:

轻松管理一组日志表。例如,您可以将不同月份的数据放入单独的表中,压缩这些表的部分内容,然后创建一个将它们作为一个整体使用的MERGE 表。

实现更快的速度。您可以根据某些条件对大型只读表进行分区,并将单独的表放置在不同的磁盘上。以这种方式构建的MERGE 表比使用单个大表要快得多。

执行更有效的搜索。如果您确切地知道要查找的内容,则可以仅搜索某些查询的基础表,并使用MERGE 表进行其他查询。您还可以使用重叠表集创建许多不同的MERGE 表。

进行更有效的修复。修复映射到MERGE 表的各个小表比修复单个大表更容易。

立即将多个表映射到一个表。 MERGE 表使用各个表的索引,因此您无需维护自己的索引。因此,创建或重新映射MERGE 表集合非常快。 (创建MERGE表时,即使没有创建索引,也必须指定索引定义。)

如果您有一组表并且可以根据需要创建一个大表,则可以根据需要从中创建MERGE 表。这要快得多并且节省大量磁盘空间。

超出操作系统文件大小限制。每个MyISAM 表都受到此限制,但MyISAM 表的集合则不受此限制。

您可以通过定义映射到单个表的MERGE 表来为MyISAM 表创建别名或同义词。这样做对性能影响很小(每次读取只需几次间接调用和memcpy() 调用)。

MERGE 表的缺点是:

您只能使用同一个MyISAM 表来创建MERGE 表。

某些MyISAM 功能不可用于MERGE 表。例如,您不能在MERGE 表上创建FULLTEXT 索引。 (您可以在基础MyISAM 表上创建FULLTEXT 索引,但不能使用全文搜索来搜索MERGE 表。)

如果MERGE 表是非临时的,则所有基础MyISAM 表都必须是非临时的。如果MERGE表是临时表,那么MyISAM表可以是临时表和非临时表的任意组合。

MERGE 表比MyISAM 表使用更多的文件描述符。如果有10 个客户端使用映射到10 个表的MERGE 表,则服务器使用(10 10) + 10 个文件描述符。 (每个客户端10 个数据文件描述符,客户端之间共享10 个索引文件描述符)。

索引读取速度很慢。读取索引时,MERGE 存储引擎必须对所有基础表发出读取操作,以确定哪个表最接近特定索引值。要读取下一个索引值,MERGE 存储引擎必须搜索读取缓冲区以查找下一个值。仅当索引缓冲区耗尽时,存储引擎才必须读取下一个索引块。这使得MERGE 索引对于eq_ref 搜索显着变慢,但对于ref 搜索则不然。有关eq_ref 和ref 的更多信息,请参阅EXPLAIN 语句。

18.7.2 MERGE 表问题

原文:dev.mysql.com/doc/refman/8.0/en/merge-table-problems.html

MERGE 表的已知问题包括:

在MySQL Server 版本5.1.23 之前,可以使用非临时子MyISAM 表创建临时合并表。

从版本5.1.23 开始,MERGE 子表通过父表锁定。如果父表是临时表,则父表不被锁定,因此子表也不被锁定。并发使用MyISAM 表可能会导致数据损坏。

当您使用ALTER TABLE 将MERGE 表更改为另一个存储引擎时,到基础表的映射将丢失。相反,使用指定的存储引擎将基础MyISAM 表中的行复制到修改后的表中。

MERGE 表的INSERT_METHOD 表选项指示用于插入MERGE 表的基础MyISAM 表。但是,在MyISAM 表上使用AUTO_INCREMENT 表选项不会影响向MERGE 表中的插入,直到至少一行直接插入到MyISAM 表中。

MERGE 表无法维护整个表的唯一约束。当执行INSERT 时,数据将进入第一个或最后一个MyISAM 表(由INSERT_METHOD 选项确定)。 MySQL 保证唯一键值在该MyISAM 表中是唯一的,而且在所有基础表中也是唯一的。

REPLACE 将无法按预期工作,因为MERGE 引擎无法强制基础表集合的唯一性。两个重要事实是:

REPLACE 只能检测正在写入的基础表中的唯一键冲突(由INSERT_METHOD 选项确定)。这与MERGE 表本身的争用不同。

如果REPLACE 检测到唯一键违规,它只会更改正在写入的基础表中的相应行,即由INSERT_METHOD 选项确定的第一个或最后一个表。

类似的考虑因素适用于INSERT . ON DUPLICATE KEY UPDATE。

MERGE 表不支持分区。换句话说,MERGE 表不能分区。另外,MERGE 表的底层MyISAM 表无法分区。

不要在映射到打开的MERGE 表的表上使用ANALYZE TABLE、REPAIR TABLE、OPTIMIZE TABLE、ALTER TABLE、DROP TABLE、不带WHERE 子句的DELETE 或TRUNCATE TABLE。如果这样做,MERGE 表仍将引用原始表,这可能会导致意外结果。要解决此问题,请发出FLUSH TABLES 语句以确保在执行命名操作之前没有任何MERGE 表处于打开状态。

意外后果包括表上的MERGE 操作可能会报告表损坏。如果这种情况发生在对基础MyISAM 表进行命名操作之后,则损坏消息是伪造的。要解决此问题,请在更改MyISAM 表后发出FLUSH TABLES 语句。

在Windows上,MySQL的MERGE存储引擎表映射对上层是隐藏的,因此对MERGE表使用的表执行DROP TABLE操作没有效果。 Windows 不允许删除打开的文件,因此您必须先刷新所有MERGE 表(使用FLUSH TABLES)或删除MERGE 表,然后再删除表。

当访问表时(例如,作为SELECT 或INSERT 语句的一部分),将检查MyISAM 和MERGE 表的定义。这些检查通过比较列顺序、类型、大小和关联索引来验证表定义是否与父MERGE 表定义匹配。如果表之间存在差异,则会返回错误并且语句失败。这些检查是在打开表时完成的,因此对单个表的定义的任何更改(例如更改列、对列重新排序或更改引擎)都将导致语句失败。

MERGE表及其基础表的索引顺序必须相同。如果使用ALTER TABLE 向用于MERGE 表的表添加UNIQUE 索引,然后向MERGE 表添加非唯一索引,则如果非唯一索引,表上索引的顺序将不同索引已经存在。在基础表上。 (这是因为ALTER TABLE 将UNIQUE 索引放在非唯一索引之前,以快速检测重复键。)因此,针对具有这些索引的表的查询可能会返回意外结果。

如果您收到类似ERROR 1017 (HY000): Can\’t find file: \’tbl_name.MRG\’ (errno: 2) 的错误消息,通常意味着某些基础表没有使用MyISAM 存储引擎。确保所有这些表都是MyISAM。

MERGE 表的最大行数为2(~1.844E+19,与MyISAM 表相同)。多个MyISAM 表无法合并到行数超过此数量的单个MERGE 表中。

已知当使用与父MERGE 表具有不同行格式的基础MyISAM 表时会失败。请参阅错误#32364。

当LOCK TABLES 有效时,您无法更改非临时MERGE 表的联合列表。以下不起作用。

创建表m1 . ENGINE=MRG_MYISAM .

锁表t1写,t2写,m1写。

更改表m1 . UNION=(t1,t2) .

但是,您可以使用临时MERGE 表来实现此目的。

您不能使用CREATE . SELECT 创建临时或非临时MERGE 表。例如:

创建表m1 . ENGINE=MRG_MYISAM . 选择.

当我尝试执行此操作时,出现错误“tbl_name 不是基表”。

如果基础表包含CHAR 或BINARY 列,则MERGE 表和基础表之间的PACK_KEYS 表选项的不同值可能会产生意外结果。作为解决方法,请使用ALTER TABLE 确保所有相关表具有相同的PACK_KEYS 值。 (错误#50646)

18.8 FEDERATED 存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/federated-storage-engine.html

18.8.1 联邦存储引擎概述

18.8.2 如何创建FEDERATED 表

18.8.3 联邦存储引擎注释和技巧

18.8.4 联合存储引擎资源

FEDERATED 存储引擎允许您访问远程MySQL 数据库中的数据,而无需使用复制或集群技术。查询本地FEDERATED 表会自动从远程(联合)表中提取数据。本地表中不存储任何数据。

如果您想从源代码构建MySQL 并包含FEDERATED 存储引擎,请使用-DWITH_FEDERATED_STORAGE_ENGINE 选项调用CMake。

服务器运行时默认不启用FEDERATED存储引擎。要启用FEDERATED,MySQL 服务器二进制文件必须使用–federated 选项启动。

要查看FEDERATED 引擎的源代码,请查看MySQL 源代码分发中的storage/federated 目录。

18.8.1 FEDERATED 存储引擎概述

原文:dev.mysql.com/doc/refman/8.0/en/fed

erated-description.html

当您使用标准存储引擎(如MyISAM、CSV或InnoDB)之一创建表时,表由表定义和相关数据组成。创建FEDERATED表时,表定义相同,但数据的物理存储在远程服务器上处理。

FEDERATED表由两个元素组成:

具有数据库表的远程服务器,该表又由表定义(存储在 MySQL 数据字典中)和相关表组成。远程表的表类型可以是远程mysqld服务器支持的任何类型,包括MyISAM或InnoDB。
本地服务器具有一个数据库表,其中表定义与远程服务器上相应表的定义相匹配。表定义存储在数据字典中。本地服务器上没有数据文件。相反,表定义包括一个指向远程表的连接字符串。

在本地服务器上对FEDERATED表执行查询和语句时,通常会向本地数据文件插入、更新或删除信息的操作会被发送到远程服务器进行执行,其中它们会更新远程服务器上的数据文件或从远程服务器返回匹配的行。

FEDERATED表设置的基本结构如图 18.2,“FEDERATED 表结构”所示。

图 18.2 FEDERATED 表结构

当客户端发出引用FEDERATED表的 SQL 语句时,在本地服务器(执行 SQL 语句的地方)和远程服务器(存储数据的地方)之间的信息流如下:

存储引擎遍历FEDERATED表具有的每一列,并构造一个适当的 SQL 语句,引用远程表。
该语句使用 MySQL 客户端 API 发送到远程服务器。
远程服务器处理语句,本地服务器检索语句产生的任何结果(受影响行数或结果集)。
如果语句产生结果集,则将每列转换为FEDERATED引擎期望的内部存储引擎格式,并可以将结果显示给发出原始语句的客户端。

本地服务器使用 MySQL 客户端 C API 函数与远程服务器通信。它调用mysql_real_query()来发送语句。要读取结果集,它使用mysql_store_result()并使用mysql_fetch_row()逐行获取行。

18.8.2 如何创建 FEDERATED 表

原文:dev.mysql.com/doc/refman/8.0/en/federated-create.html

18.8.2.1 使用 CONNECTION 创建 FEDERATED 表

18.8.2.2 使用 CREATE SERVER 创建 FEDERATED 表

要创建一个FEDERATED表,您应该按照以下步骤进行:

在远程服务器上创建表。或者,记录现有表的表定义,可能使用SHOW CREATE TABLE语句。
在本地服务器上创建一个具有相同表定义的表,但添加连接信息,将本地表与远程表链接起来。

例如,您可以在远程服务器上创建以下表:

CREATE TABLE test_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT \’\’,
other INT(20) NOT NULL DEFAULT \’0\’,
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=MyISAM
DEFAULT CHARSET=utf8mb4;

要创建与远程表联合的本地表,有两种可用选项。您可以创建本地表并指定连接字符串(包含服务器名称、登录、密码),用于使用CONNECTION连接到远程表,或者您可以使用之前使用CREATE SERVER语句创建的现有连接。

重要

当您创建本地表时,它必须具有与远程表相同的字段定义。

注意

通过为主机上的表添加索引,可以提高FEDERATED表的性能。优化发生的原因是发送到远程服务器的查询包含WHERE子句的内容,并且被发送到远程服务器并在本地执行。这减少了网络流量,否则会请求整个表从服务器传输到本地进行处理。

原文:dev.mysql.com/doc/refman/8.0/en/federated-create-connection.html

18.8.2.1 使用 CONNECTION 创建一个 FEDERATED 表

要使用第一种方法,你必须在 CREATE TABLE 语句中的引擎类型之后指定 CONNECTION 字符串。例如:

CREATE TABLE federated_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT \’\’,
other INT(20) NOT NULL DEFAULT \’0\’,
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=utf8mb4
CONNECTION=\’mysql://fed_user@remote_host:9306/federated/test_table\’;

注意

CONNECTION 取代了一些早期版本的 MySQL 中使用的 COMMENT。

CONNECTION 字符串包含连接到包含数据物理存储的远程服务器的信息。连接字符串指定服务器名称、登录凭据、端口号和数据库/表信息。在这个例子中,远程表位于服务器 remote_host 上,使用端口 9306。名称和端口号应该与你想要用作远程表的远程 MySQL 服务器实例的主机名(或 IP 地址)和端口号匹配。

连接字符串的格式如下:

*scheme*://*user_name*[:*password*]@*host_name*[:*port_num*]/*db_name*/*tbl_name*

其中:

scheme: 一个被识别的连接协议。目前只支持 mysql 作为 scheme 的值。
user_name: 连接的用户名。这个用户必须在远程服务器上创建,并且必须具有执行所需操作(SELECT, INSERT, UPDATE等)所需的适当权限。
password: (可选)user_name 对应的密码。
host_name: 远程服务器的主机名或 IP 地址。
port_num: (可选)远程服务器的端口号。默认值为 3306。
db_name: 持有远程表的数据库名称。
tbl_name: 远程表的名称。本地表和远程表的名称不必匹配。

示例连接字符串:

CONNECTION=\’mysql://username:password@hostname:port/database/tablename\’
CONNECTION=\’mysql://username@hostname/database/tablename\’
CONNECTION=\’mysql://username:password@hostname/database/tablename\’

原文:dev.mysql.com/doc/refman/8.0/en/federated-create-server.html

18.8.2.2 使用 CREATE SERVER 创建 FEDERATED 表

如果您在同一服务器上创建多个 FEDERATED 表,或者想简化创建 FEDERATED 表的过程,可以使用 CREATE SERVER 语句来定义服务器连接参数,就像您使用 CONNECTION 字符串一样。

CREATE SERVER 语句的格式为:

CREATE SERVER
*server_name*
FOREIGN DATA WRAPPER *wrapper_name*
OPTIONS (*option* [, *option*] …)

server_name 在创建新的 FEDERATED 表时用于连接字符串。

例如,要创建与 CONNECTION 字符串相同的服务器连接:

CONNECTION=\’mysql://fed_user@remote_host:9306/federated/test_table\’;

您将使用以下语句:

CREATE SERVER fedlink
FOREIGN DATA WRAPPER mysql
OPTIONS (USER \’fed_user\’, HOST \’remote_host\’, PORT 9306, DATABASE \’federated\’);

要创建一个使用此连接的 FEDERATED 表,仍然使用 CONNECTION 关键字,但指定您在 CREATE SERVER 语句中使用的名称。

CREATE TABLE test_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT \’\’,
other INT(20) NOT NULL DEFAULT \’0\’,
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=utf8mb4
CONNECTION=\’fedlink/test_table\’;

此示例中的连接名称包含连接名称(fedlink)和要链接到的表名称(test_table),用斜杠分隔。 如果只指定连接名称而没有表名称,则使用本地表的表名称。

有关 CREATE SERVER 的更多信息,请参见 Section 15.1.18, “CREATE SERVER Statement”。

CREATE SERVER 语句接受与 CONNECTION 字符串相同的参数。 CREATE SERVER 语句会更新 mysql.servers 表中的行。 有关连接字符串中参数、CREATE SERVER 语句选项以及 mysql.servers 表中列之间的对应关系,请参考以下表格。 供参考,CONNECTION 字符串的格式如下:

*scheme*://*user_name*[:*password*]@*host_name*[:*port_num*]/*db_name*/*tbl_name*

描述CONNECTION 字符串CREATE SERVER 选项mysql.servers 列连接方案schemewrapper_nameWrapper远程用户user_nameUSERUsername远程密码passwordPASSWORDPassword远程主机host_nameHOSTHost远程端口port_numPORTPort远程数据库db_nameDATABASEDb

18.8.3 FEDERATED 存储引擎注意事项和提示

原文:dev.mysql.com/doc/refman/8.0/en/federated-usagenotes.html

在使用FEDERATED存储引擎时,应注意以下几点:

FEDERATED表可以被复制到其他副本,但必须确保副本服务器能够使用在CONNECTION字符串(或mysql.servers表中的行)中定义的用户/密码组合连接到远程服务器。
以下项目指示了FEDERATED存储引擎支持和不支持的功能:

远程服务器必须是一个 MySQL 服务器。
FEDERATED表指向的远程表在通过FEDERATED表访问之前必须存在。
一个FEDERATED表可以指向另一个表,但必须小心不要创建循环。
FEDERATED表不支持通常意义上的索引;因为对表数据的访问是远程处理的,实际上是远程表利用索引。这意味着,对于无法使用任何索引并因此需要完整表扫描的查询,服务器会从远程表中获取所有行并在本地进行过滤。这将发生无论此SELECT语句中使用的任何WHERE或LIMIT;这些子句在本地应用于返回的行。
未能使用索引的查询可能导致性能不佳和网络负载过重。此外,由于返回的行必须存储在内存中,这样的查询也可能导致本地服务器交换,甚至挂起。
在创建FEDERATED表时应当小心,因为来自等效MyISAM或其他表的索引定义可能不被支持。例如,如果表在任何VARCHAR、TEXT或BLOB列上使用索引前缀,则创建FEDERATED表将失败。以下使用MyISAM的定义是有效的:
CREATE TABLE `T1`(`A` VARCHAR(100),UNIQUE KEY(`A`(30))) ENGINE=MYISAM;
此示例中的键前缀与FEDERATED引擎不兼容,等效语句将失败:
CREATE TABLE `T1`(`A` VARCHAR(100),UNIQUE KEY(`A`(30))) ENGINE=FEDERATED
CONNECTION=\’MYSQL://127.0.0.1:3306/TEST/T1\’;
如果可能的话,在远程服务器和本地服务器创建表时,应尽量分开列和索引定义,以避免这些索引问题。
在内部,实现使用SELECT、INSERT、UPDATE和DELETE,但不使用HANDLER。
FEDERATED存储引擎支持SELECT、INSERT、UPDATE、DELETE、TRUNCATE TABLE和索引。它不支持ALTER TABLE或任何直接影响表结构的数据定义语言语句,除了DROP TABLE。当前的实现不使用预处理语句。
FEDERATED接受INSERT … ON DUPLICATE KEY UPDATE语句,但如果发生重复键违规,该语句将失败并显示错误。
不支持事务。
FEDERATED执行批量插入处理,使多行以批量方式发送到远程表,从而提高性能。此外,如果远程表是事务性的,它可以使远程存储引擎在发生错误时正确执行语句回滚。此功能具有以下限制:

插入的大小不能超过服务器之间的最大数据包大小。如果插入超过此大小,它将被分成多个数据包,可能会出现回滚问题。
不会对INSERT … ON DUPLICATE KEY UPDATE进行批量插入处理。
FEDERATED引擎无法知道远程表是否发生了更改。原因是该表必须像数据文件一样工作,除了数据库系统之外不会被任何其他东西写入。如果远程数据库发生任何更改,本地表中的数据完整性可能会受到破坏。
在使用CONNECTION字符串时,密码中不能使用’@\’字符。您可以通过使用CREATE SERVER语句创建服务器连接来绕过此限制。
insert_id和timestamp选项不会传播到数据提供程序。
对FEDERATED表执行的任何DROP TABLE语句仅删除本地表,而不是远程表。
不支持对FEDERATED表进行用户定义的分区。

18.8.4 FEDERATED 存储引擎资源

原文:dev.mysql.com/doc/refman/8.0/en/federated-storage-engine-resources.html

以下是可用于 FEDERATED 存储引擎的额外资源:

一个专门致力于 FEDERATED 存储引擎的论坛可在 forums.mysql.com/list.php?105 找到。

18.9 EXAMPLE存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/example-storage-engine.html

EXAMPLE存储引擎是一个什么都不做的存根引擎。它的目的是作为 MySQL 源代码中的一个示例,展示如何开始编写新的存储引擎。因此,它主要是为开发人员感兴趣。

如果您从源代码构建 MySQL,并希望启用EXAMPLE存储引擎,请使用CMake调用-DWITH_EXAMPLE_STORAGE_ENGINE选项。

要查看EXAMPLE引擎的源代码,请查看 MySQL 源代码分发中的storage/example目录。

当您创建一个EXAMPLE表时,不会创建任何文件。表中无法存储任何数据。检索将返回一个空结果。

mysql> CREATE TABLE test (i INT) ENGINE = EXAMPLE;
Query OK, 0 rows affected (0.78 sec)
mysql> INSERT INTO test VALUES(1),(2),(3);
ERROR 1031 (HY000): Table storage engine for \’test\’ doesn\’t »
have this option
mysql> SELECT * FROM test;
Empty set (0.31 sec)

EXAMPLE存储引擎不支持索引。

EXAMPLE存储引擎不支持分区。

18.10 其他存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/storage-engines-other.html

其他存储引擎可能来自已使用自定义存储引擎接口的第三方和社区成员。

不支持 MySQL 的第三方引擎。有关更多信息、文档、安装指南、错误报告或任何关于这些引擎的帮助或协助,请直接联系引擎开发者。

欲了解更多关于开发可与可插拔存储引擎架构一起使用的自定义存储引擎的信息,请参阅 MySQL 内部:编写自定义存储引擎。

18.11 MySQL 存储引擎架构概述

原文:dev.mysql.com/doc/refman/8.0/en/pluggable-storage-overview.html

18.11.1 可插拔存储引擎架构

18.11.2 共同的数据库服务器层

MySQL 可插拔存储引擎架构使数据库专业人员能够为特定应用需求选择专门的存储引擎,同时完全屏蔽了管理任何特定应用编码需求的需要。MySQL 服务器架构将应用程序员和数据库管理员与存储级别的所有低级实现细节隔离开来,提供一致且易于使用的应用模型和 API。因此,尽管不同存储引擎具有不同的功能,但应用程序被屏蔽免受这些差异的影响。

MySQL 可插拔存储引擎架构显示在图 18.3,“带有可插拔存储引擎的 MySQL 架构”中。

图 18.3 MySQL 架构与可插拔存储引擎

可插拔存储引擎架构提供了一套标准的管理和支持服务,这些服务在所有底层存储引擎中都是共同的。存储引擎本身是数据库服务器的组件,实际上在物理服务器级别上执行对底层数据的操作。

这种高效且模块化的架构为那些希望专门针对特定应用需求(如数据仓库、事务处理或高可用性情况)的人提供了巨大的好处,同时享受利用独立于任何一个存储引擎的一组接口和服务的优势。

应用程序员和数据库管理员通过位于存储引擎之上的连接器 API 和服务层与 MySQL 数据库进行交互。如果应用程序的更改带来了需要更改底层存储引擎或添加一个或多个存储引擎以支持新需求的要求,那么不需要进行重大的编码或流程更改即可使事情正常运行。MySQL 服务器架构通过提供一致且易于使用的 API 来屏蔽应用程序免受存储引擎的底层复杂性。

18.11.1 可插拔存储引擎架构

原文:dev.mysql.com/doc/refman/8.0/en/pluggable-storage.html

MySQL 服务器使用可插拔存储引擎架构,允许将存储引擎加载到运行中的 MySQL 服务器中并从中卸载。

安装存储引擎

在使用存储引擎之前,必须使用INSTALL PLUGIN语句将存储引擎插件共享库加载到 MySQL 中。例如,如果EXAMPLE引擎插件命名为example,共享库命名为ha_example.so,则可以使用以下语句加载:

INSTALL PLUGIN example SONAME \’ha_example.so\’;

要安装可插拔存储引擎,插件文件必须位于 MySQL 插件目录中,并且发出INSTALL PLUGIN语句的用户必须对mysql.plugin表具有INSERT权限。

共享库必须位于 MySQL 服务器插件目录中,其位置由plugin_dir系统变量给出。

卸载存储引擎

要卸载存储引擎,请使用UNINSTALL PLUGIN语句:

UNINSTALL PLUGIN example;

如果卸载一个现有表需要的存储引擎,那些表将变得无法访问,但仍然存在于磁盘上(如果适用)。在卸载存储引擎之前,请确保没有表使用存储引擎。

18.11.2 通用数据库服务器层

原文:dev.mysql.com/doc/refman/8.0/en/pluggable-storage-common-layer.html

MySQL 可插拔存储引擎是 MySQL 数据库服务器中负责执行实际数据 I/O 操作的组件,同时启用和强制执行针对特定应用需求的某些功能集。使用特定存储引擎的一个主要好处是,你只会获得特定应用所需的功能,因此在数据库中的系统开销更少,最终结果是更高效和更高性能的数据库。这也是 MySQL 一直以来以高性能而闻名的原因之一,在行业标准基准测试中与专有的单体数据库相匹敌或超越。

从技术角度来看,存储引擎中有哪些独特的支持基础设施组件?一些关键的特性差异包括:

并发性:一些应用程序对锁定要求更加精细(如行级锁)而另一些则不然。选择正确的锁定策略可以减少开销,从而提高整体性能。这个领域还包括支持诸如多版本并发控制或“快照”读取等功能。
事务支持:并非每个应用程序都需要事务,但对于那些需要的应用程序,有非常明确定义的要求,如 ACID 兼容性等。
引用完整性:需要服务器通过 DDL 定义的外键来强制执行关系数据库的引用完整性。
物理存储:这涉及从表和索引的整体页面大小到用于存储数据的格式以及物理磁盘的一切。
索引支持:不同的应用场景往往受益于不同的索引策略。每个存储引擎通常都有自己的索引方法,尽管一些(如 B 树索引)几乎适用于所有引擎。
内存缓存:不同的应用程序对某些内存缓存策略的响应更好,因此尽管一些内存缓存对所有存储引擎都是通用的(例如用于用户连接的缓存),但其他的只有在特定存储引擎投入使用时才会被唯一定义。
性能辅助:这包括用于并行操作的多个 I/O 线程,线程并发性,数据库检查点,批量插入处理等。
其他目标特性:这可能包括对地理空间操作的支持,对某些数据操作的安全限制以及其他类似的功能。

每组可插拔存储引擎基础设施组件都旨在为特定应用程序提供一组选择性的优势。相反,避免一组组件功能有助于减少不必要的开销。可以说,了解特定应用程序的一组要求并选择适当的 MySQL 存储引擎对整个系统的效率和性能都会产生显著影响。

第十九章 复制

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

目录

19.1 配置复制

19.1.1 基于二进制日志文件位置的复制配置概述

19.1.2 设置基于二进制日志文件位置的复制

19.1.3 使用全局事务标识符进行复制

19.1.4 在在线服务器上更改 GTID 模式

19.1.5 MySQL 多源复制

19.1.6 复制和二进制日志选项和变量

19.1.7 常见复制管理任务

19.2 复制实现

19.2.1 复制格式

19.2.2 复制通道

19.2.3 复制线程

19.2.4 中继日志和复制元数据存储库

19.2.5 服务器如何评估复制过滤规则

19.3 复制安全性

19.3.1 设置复制以使用加密连接

19.3.2 加密二进制日志文件和中继日志文件

19.3.3 复制权限检查

19.4 复制解决方案

19.4.1 使用复制进行备份

19.4.2 处理复制副本意外停止

19.4.3 监控基于行的复制

19.4.4 使用不同源和副本存储引擎进行复制

19.4.5 使用复制进行扩展

19.4.6 将不同数据库复制到不同副本

19.4.7 改善复制性能

19.4.8 在故障转移期间切换源

19.4.9 使用异步连接故障转移切换源和副本

19.4.10 半同步复制

19.4.11 延迟复制

19.5 复制注意事项和提示

19.5.1 复制功能和问题

19.5.2 MySQL 版本之间的复制兼容性

19.5.3 升级复制拓扑

19.5.4 复制故障排除

19.5.5 如何报告复制错误或问题

复制使得来自一个 MySQL 数据库服务器(称为源)的数据可以被复制到一个或多个 MySQL 数据库服务器(称为副本)上。默认情况下,复制是异步的;副本不需要永久连接以接收来自源端的更新。根据配置,可以复制所有数据库、选定的数据库,甚至是数据库中的选定表。

MySQL 中复制的优势包括:

扩展解决方案 – 将负载分散在多个副本之间以提高性能。在这种环境中,所有写入和更新必须在源服务器上进行。然而,读取可以在一个或多个副本上进行。这种模型可以提高写入性能(因为源端专用于更新),同时大大提高跨越越来越多副本的读取速度。
数据安全性 – 因为副本可以暂停复制过程,所以可以在副本上运行备份服务,而不会破坏相应的源数据。
分析 – 实时数据可以在源端创建,而信息分析可以在副本上进行,而不会影响源端的性能。
远程数据分发 – 可以使用复制在远程站点创建数据的本地副本,而无需永久访问源端。

有关如何在这种情况下使用复制的信息,请参阅第 19.4 节,“复制解决方案”。

MySQL 8.0 支持不同的复制方法。传统方法基于从源端二进制日志复制事件,并要求在源端和副本之间同步日志文件和位置。基于全局事务标识符(GTIDs)的新方法是事务性的,因此不需要处理日志文件或这些文件中的位置,这极大简化了许多常见的复制任务。使用 GTIDs 进行复制可以保证源端和副本之间的一致性,只要在源端提交的所有事务也已在副本上应用。有关 MySQL 中 GTIDs 和基于 GTID 的复制的更多信息,请参阅第 19.1.3 节,“使用全局事务标识符进行复制”。有关使用基于二进制日志文件位置的复制的信息,请参阅第 19.1 节,“配置复制”。

MySQL 中的复制支持不同类型的同步。最初的同步类型是单向异步复制,其中一个服务器充当源,而一个或多个其他服务器充当副本。这与NDB Cluster的同步复制形成对比(参见第二十五章,MySQL NDB Cluster 8.0)。在 MySQL 8.0 中,除了内置的异步复制外,还支持半同步复制。通过半同步复制,在源上执行的提交会在返回到执行事务的会话之前阻塞,直到至少一个副本确认已接收并记录了事务的事件;请参见第 19.4.10 节,“半同步复制”。MySQL 8.0 还支持延迟复制,使得副本故意落后源至少指定的时间量;请参见第 19.4.11 节,“延迟复制”。对于需要同步复制的情况,请使用 NDB Cluster(参见第二十五章,MySQL NDB Cluster 8.0)。

有许多可用的解决方案可用于设置服务器之间的复制,最佳使用方法取决于数据的存在以及您正在使用的引擎类型。有关可用选项的更多信息,请参见第 19.1.2 节,“设置基于二进制日志文件位置的复制”。

复制格式有两种核心类型,基于语句的复制(SBR),它复制整个 SQL 语句,以及基于行的复制(RBR),它只复制已更改的行。您还可以使用第三种类型,混合基于复制(MBR)。有关不同复制格式的更多信息,请参见第 19.2.1 节,“复制格式”。

复制通过许多不同的选项和变量进行控制。有关更多信息,请参见第 19.1.6 节,“复制和二进制日志选项和变量”。还可以应用额外的安全措施到复制拓扑中,如第 19.3 节,“复制安全性”中所述。

你可以使用复制来解决许多不同的问题,包括性能、支持不同数据库的备份,以及作为缓解系统故障的更大解决方案的一部分。有关如何解决这些问题的信息,请参见第 19.4 节,“复制解决方案”。

关于不同数据类型和语句在复制过程中的处理方式的注释和提示,包括复制功能的详细信息、版本兼容性、升级以及潜在问题及其解决方法,请参见第 19.5 节,“复制注释和提示”。对于那些对 MySQL 复制新手经常提出的一些问题的答案,请参见第 A.14 节,“MySQL 8.0 FAQ: 复制”。

关于复制实现、复制工作原理、二进制日志的过程和内容、后台线程以及用于决定如何记录和复制语句的规则的详细信息,请参见第 19.2 节,“复制实现”。

19.1 配置复制

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

19.1.1 基于二进制日志文件位置的复制配置概述

19.1.2 设置基于二进制日志文件位置的复制

19.1.3 具有全局事务标识符的复制

19.1.4 在在线服务器上更改 GTID 模式

19.1.5 MySQL 多源复制

19.1.6 复制和二进制日志选项和变量

19.1.7 常见的复制管理任务

本节描述了如何配置 MySQL 中可用的不同类型的复制,并包括复制环境所需的设置和配置,包括为创建新的复制环境提供逐步说明。本节的主要组成部分包括:

对于使用二进制日志文件位置设置两个或更多服务器进行复制的指南,请参阅第 19.1.2 节,“设置基于二进制日志文件位置的复制”,处理服务器的配置并提供在源和副本之间复制数据的方法。
对于使用 GTID 事务设置两个或更多服务器进行复制的指南,请参阅第 19.1.3 节,“具有全局事务标识符的复制”,处理服务器的配置。
二进制日志中记录的事件使用多种格式。这些被称为基于语句的复制(SBR)或基于行的复制(RBR)。第三种类型,混合格式复制(MIXED),在适当时自动使用 SBR 或 RBR 复制以充分利用 SBR 和 RBR 格式的优势。不同的格式在第 19.2.1 节,“复制格式”中讨论。
提供有关适用于复制的不同配置选项和变量的详细信息在第 19.1.6 节,“复制和二进制日志选项和变量”中。
一旦启动,复制过程应该需要很少的管理或监控。但是,对于您可能想要执行的常见任务的建议,请参阅第 19.1.7 节,“常见的复制管理任务”。

19.1.1 基于二进制日志文件位置的复制配置概述

原文:dev.mysql.com/doc/refman/8.0/en/binlog-replication-configuration-overview.html

本节描述了基于二进制日志文件位置方法的 MySQL 服务器之间的复制,其中作为源(数据库更改发生的地方)运行的 MySQL 实例将更新和更改写入二进制日志作为“事件”。二进制日志中的信息根据记录的数据库更改以不同的日志格式存储。复制品被配置为从源读取二进制日志,并在复制品的本地数据库上执行二进制日志中的事件。

每个复制品接收二进制日志的整个内容副本。复制品有责任决定应执行二进制日志中的哪些语句。除非另有规定,否则源的二进制日志中的所有事件都将在复制品上执行。如果需要,可以配置复制品仅处理适用于特定数据库或表的事件。

重要提示

无法配置源仅记录某些事件。

每个复制品保留二进制日志坐标的记录:它已从源读取和处理的文件名和文件中位置。这意味着多个复制品可以连接到源并在同一二进制日志的不同部分执行。由于复制品控制此过程,因此可以连接和断开单个复制品而不影响源的操作。此外,因为每个复制品记录了二进制日志中的当前位置,所以可以断开复制品,重新连接,然后恢复处理。

源和每个复制品必须配置一个唯一的 ID(使用server_id系统变量)。此外,每个复制品必须配置有关源主机名、日志文件名和文件中位置的信息。这些细节可以通过 MySQL 会话内的CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)在复制品上进行控制。这些细节存储在复制品的连接元数据存储库中(参见第 19.2.4 节,“中继日志和复制元数据存储库”)。

19.1.2 设置基于二进制日志文件位置的复制

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

19.1.2.1 设置复制源配置

19.1.2.2 设置副本配置

19.1.2.3 为复制创建用户

19.1.2.4 获取复制源的二进制日志坐标

19.1.2.5 选择数据快照方法

19.1.2.6 设置副本

19.1.2.7 在副本上设置源配置

19.1.2.8 将副本添加到复制环境

本节描述了如何设置 MySQL 服务器以使用基于二进制日志文件位置的复制。有许多不同的设置复制的方法,要使用的确切方法取决于您如何设置复制,以及源数据库中是否已经有要复制的数据。

提示

要部署多个 MySQL 实例,您可以使用 InnoDB Cluster,它使您能够轻松管理一组 MySQL 服务器实例在 MySQL Shell 中。InnoDB Cluster 将 MySQL Group Replication 包装在一个编程环境中,使您可以轻松部署一组 MySQL 实例以实现高可用性。此外,InnoDB Cluster 与 MySQL Router 无缝接口,使您的应用程序可以连接到集群而无需编写自己的故障转移过程。然而,对于不需要高可用性的类似用例,您可以使用 InnoDB ReplicaSet。有关 MySQL Shell 的安装说明,请参见这里。

有一些通用任务适用于所有设置:

在源端,您必须确保启用了二进制日志记录,并配置一个唯一的服务器 ID。这可能需要重新启动服务器。参见 Section 19.1.2.1, “设置复制源配置”。
在每个要连接到源的副本上,您必须配置一个唯一的服务器 ID。这可能需要重新启动服务器。参见 Section 19.1.2.2, “设置副本配置”。
可选地,为您的副本创建一个单独的用户,用于在复制时与源进行身份验证以读取二进制日志。参见第 19.1.2.3 节,“为复制创建用户”。
在创建数据快照或启动复制过程之前,在源上记录二进制日志中的当前位置。在配置副本时,您需要这些信息,以便副本知道在二进制日志中从哪里开始执行事件。参见第 19.1.2.4 节,“获取复制源二进制日志坐标”。
如果您已经在源上有数据并希望使用它来同步副本,您需要创建一个数据快照将数据复制到副本。您正在使用的存储引擎会影响您如何创建快照。当您使用MyISAM时,您必须停止在源上处理语句以获取读锁,然后获取其当前的二进制日志坐标并转储其数据,然后允许源继续执行语句。如果您不停止执行语句,则数据转储和源状态信息将不匹配,导致副本上的数据库不一致或损坏。有关复制MyISAM源的更多信息,请参见第 19.1.2.4 节,“获取复制源二进制日志坐标”。如果您使用InnoDB,则不需要读锁,只需一个足够长的事务来传输数据快照即可。有关更多信息,请参见第 17.19 节,“InnoDB 和 MySQL 复制”。
配置副本以设置连接到源的设置,如主机名、登录凭据和二进制日志文件名和位置。参见第 19.1.2.7 节,“在副本上设置源配置”。
根据您的系统,在源和副本上实施特定于复制的安全措施。参见第 19.3 节,“复制安全”。

注意

设置过程中的某些步骤需要SUPER权限。如果您没有此权限,则可能无法启用复制。

配置基本选项后,选择您的场景:

要为不包含任何数据的新源和副本的新安装设置复制,请参阅第 19.1.2.6.1 节,“使用新源和副本设置复制”。
要设置使用现有 MySQL 服务器数据进行新源的复制,请参阅第 19.1.2.6.2 节,“使用现有数据设置复制”。
要向现有复制环境添加副本,请参阅第 19.1.2.8 节,“向复制环境添加副本”。

在管理 MySQL 复制服务器之前,请阅读本章的全部内容,并尝试执行第 15.4.1 节,“用于控制源服务器的 SQL 语句”和第 15.4.2 节,“用于控制副本服务器的 SQL 语句”中提到的所有语句,并熟悉第 19.1.6 节,“复制和二进制日志选项和变量”中描述的复制启动选项。

原文:dev.mysql.com/doc/refman/8.0/en/replication-howto-masterbaseconfig.html

19.1.2.1 设置复制源配置

要配置源端使用基于二进制日志文件位置的复制,您必须确保启用了二进制日志记录,并建立一个唯一的服务器 ID。

在复制拓扑结构中,每个服务器都必须配置一个唯一的服务器 ID,您可以使用server_id系统变量来指定。该服务器 ID 用于标识复制拓扑结构中的各个服务器,必须是介于 1 和(2³²)−1 之间的正整数。从 MySQL 8.0 开始,默认的server_id值为 1。您可以通过发出类似以下语句来动态更改server_id的值:

SET GLOBAL server_id = 2;

您可以自行组织和选择服务器 ID,只要每个服务器 ID 与复制拓扑结构中任何其他服务器正在使用的每个其他服务器 ID 不同即可。请注意,如果以前为服务器 ID 设置了值 0(这是早期版本的默认值),则必须重新启动服务器以使用新的非零服务器 ID 初始化源端。否则,当您更改服务器 ID 时,���非进行其他需要重新启动的配置更改,否则不需要重新启动服务器。

源端需要启用二进制日志记录,因为二进制日志是从源端到其副本进行更改复制的基础。二进制日志记录默认启用(log_bin系统变量设置为 ON)。–log-bin选项告诉服务器要使用的二进制日志文件的基本名称。建议您指定此选项,以便为二进制日志文件指定非默认基本名称,这样如果主机名更改,您可以轻松地继续使用相同的二进制日志文件名(参见 Section B.3.7, “Known Issues in MySQL”)。如果之前在源端使用–skip-log-bin选项禁用了二进制日志记录,则必须在不带此选项的情况下重新启动服务器以启用它。

注意

以下选项也会影响源端:

在使用带有事务的InnoDB的复制设置中,为了获得最大的耐久性和一致性,您应该在源端的my.cnf文件中使用innodb_flush_log_at_trx_commit=1和sync_binlog=1。
确保源端未启用skip_networking系统变量。如果网络已禁用,则副本无法与源端通信,复制将失败。

原文:dev.mysql.com/doc/refman/8.0/en/replication-howto-slavebaseconfig.html

19.1.2.2 设置复制品配置

每个复制品必须具有唯一的服务器 ID,由server_id系统变量指定。如果您正在设置多个复制品,则每个复制品必须具有与源和任何其他复制品不同的唯一server_id值。如果复制品的服务器 ID 尚未设置,或当前值与您为源或其他复制品选择的值冲突,则必须更改它。

默认server_id值为 1。您可以通过发出类似以下语句来动态更改server_id值:

SET GLOBAL server_id = 21;

请注意,服务器 ID 的值为 0 会阻止复制品连接到源。如果该服务器 ID 值(这是早期版本中的默认值)以前已设置,则必须重新启动服务器以使用新的非零服务器 ID 初始化复制品。否则,当您更改服务器 ID 时,不需要重新启动服务器,除非进行其他需要重新启动的配置更改。例如,如果服务器上已禁用二进制日志记录,并且您希望在复制品上启用它,则需要重新启动服务器才能启用此功能。

如果要关闭复制品服务器,可以编辑配置文件的[mysqld]部分以指定唯一的服务器 ID。例如:

[mysqld]
server-id=21

所有服务器默认启用二进制日志记录。复制品不需要启用二进制日志记录才能进行复制。但是,复制品上启用二进制日志记录意味着复制品的二进制日志可用于数据备份和崩溃恢复。已启用二进制日志记录的复制品也可以用作更复杂复制拓扑的一部分。例如,您可能希望使用此链接安排设置复制服务器:

A -> B -> C

这里,A充当复制品B的源,而B充当复制品C的源。为了使其正常工作,B必须既是源又是复制品。从A接收到的更新必须由B记录到其二进制日志中,以便传递给C。除了二进制日志记录外,此复制拓扑结构需要启用系统变量log_replica_updates(从 MySQL 8.0.26 开始)或log_slave_updates(在 MySQL 8.0.26 之前)才能正常工作。启用复制更新后,复制品会将从源接收并由复制品的 SQL 线程执行的更新写入复制品自己的二进制日志中。系统变量log_replica_updates或log_slave_updates默认启用。

如果需要在复制品上禁用二进制日志记录或复制更新记录,可以通过为复制品指定–skip-log-bin和–log-replica-updates=OFF或–log-slave-updates=OFF选项来实现。如果决定在复制品上重新启用这些功能,请删除相关选项并重新启动服务器。

原文:dev.mysql.com/doc/refman/8.0/en/replication-howto-repuser.html

19.1.2.3 为复制创建用户

每个副本使用 MySQL 用户名和密码连接到源端,因此必须在源端上有一个副本可以使用的用户帐户。当您设置副本时,通过CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)指定用户名称。任何帐户都可以用于此操作,只要已授予REPLICATION SLAVE权限。您可以选择为每个副本创建不同的帐户,或者使用相同的帐户连接到源端以供每个副本使用。

尽管您不必专门为复制创建帐户,但您应该知道复制用户名和密码以明文形式存储在复制连接元数据存储库mysql.slave_master_info中(参见 Section 19.2.4.2,“复制元数据存储库”)。因此,您可能希望创建一个仅具有复制过程权限的单独帐户,以最大程度地减少其他帐户遭受威胁的可能性。

要创建一个新帐户,请使用CREATE USER。要为此帐户授予复制所需的权限,请使用GRANT语句。如果您仅为复制目的创建一个帐户,则该帐户只需要REPLICATION SLAVE权限。例如,要设置一个名为repl的新用户,该用户可以从example.com域内的任何主机连接进行复制,请在源端执行以下语句:

mysql> CREATE USER \’repl\’@\’%.example.com\’ IDENTIFIED BY \’*password*\’;
mysql> GRANT REPLICATION SLAVE ON *.* TO \’repl\’@\’%.example.com\’;

有关用户帐户操作语句的更多信息,请参见 Section 15.7.1,“帐户管理语句”。

重要提示

要使用使用caching_sha2_password插件进行身份验证的用户帐户连接到源,您必须按照 Section 19.3.1, “Setting Up Replication to Use Encrypted Connections”中描述的设置安装安全连接,或者启用不加密的连接以支持使用 RSA 密钥对进行密码交换。caching_sha2_password认证插件是从 MySQL 8.0 开始新用户的默认选项(有关详细信息,请参见 Section 8.4.1.2, “Caching SHA-2 Pluggable Authentication”)。如果您创建或用于复制的用户帐户(由MASTER_USER选项指定)使用此认证插件,并且您没有使用安全连接,则必须启用基于 RSA 密钥对的密码交换以成功连接。

原文:dev.mysql.com/doc/refman/8.0/en/replication-howto-masterstatus.html

19.1.2.4 获取复制源二进制日志坐标

要配置副本以在正确位置开始复制过程,您需要记录源在其二进制日志中的当前坐标。

警告

此过程使用FLUSH TABLES WITH READ LOCK,会阻塞InnoDB表的COMMIT操作。

如果您计划关闭源以创建数据快照,则可以选择跳过此过程,而是将二进制日志索引文件的副本与数据快照一起存储。在那种情况下,源在重新启动时会创建一个新的二进制日志文件。因此,副本必须开始复制过程的源二进制日志坐标是该新文件的开头,即在复制的二进制日志索引文件中列出的文件之后的源上的下一个二进制日志文件。

要获取源二进制日志坐标,请按照以下步骤操作:

在源上启动一个会话,通过命令行客户端连接到它,并通过执行FLUSH TABLES WITH READ LOCK语句刷新所有表并阻止写入语句:
mysql> FLUSH TABLES WITH READ LOCK;
警告
保持发出FLUSH TABLES语句的客户端运行,以使读锁保持生效。如果退出客户端,则锁将被释放。
在源的另一个会话中,使用SHOW MASTER STATUS语句确定当前二进制日志文件名和位置:
mysql> SHOW MASTER STATUS\\G
*************************** 1\\. row ***************************
File: mysql-bin.000003
Position: 73
Binlog_Do_DB: test
Binlog_Ignore_DB: manual, mysql
Executed_Gtid_Set: 3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5 1 row in set (0.00 sec)
File列显示日志文件的名称,Position列显示文件内的位置。在此示例中,二进制日志文件为mysql-bin.000003,位置为 73。记录这些值。在设置副本时,您将需要它们。它们代表副本应开始处理源的新更新的复制坐标。
如果源先前已禁用二进制日志记录运行,则SHOW MASTER STATUS或mysqldump –master-data显示的日志文件名和位置值为空。在这种情况下,您稍后在指定源的二进制日志文件和位置时需要使用的值是空字符串(\’\’)和4。

您现在拥有启用副本从源的二进制日志中正确位置开始读取所需的信息。

下一步取决于您在源端是否有现有数据。请选择以下选项之一:

如果您有现有数据需要在开始复制之前与副本同步,请保持客户端运行,以便锁定保持在原位。这样可以防止进行进一步的更改,从而使复制到副本的数据与源数据同步。继续查看 Section 19.1.2.5, “选择数据快照方法”。
如果您正在设置新的源和副本组合,您可以退出第一个会话以释放读锁。查看 Section 19.1.2.6.1, “使用新源和副本设置复制”以了解如何继续。

原文:dev.mysql.com/doc/refman/8.0/en/replication-snapshot-method.html

19.1.2.5 选择数据快照方法

如果源数据库包含现有数据,则需要将这些数据复制到每个副本中。有不同的方法可以从源数据库中导出数据。以下部分描述了可能的选项。

要选择适当的数据库转储方法,请在以下选项之间进行选择:

使用mysqldump工具创建要复制的所有数据库的转储。这是推荐的方法,特别是在使用InnoDB时。
如果您的数据库存储在二进制可移植文件中,则可以将原始数据文件复制到副本中。这可能比使用mysqldump并在每个副本上导入文件更有效,因为在重放INSERT语句时跳过更新索引的开销。对于诸如InnoDB之类的存储引擎,不建议这样做。
使用 MySQL Server 的克隆插件将所有数据从现有副本传输到克隆副本。有关使用此方法的说明,请参见 Section 7.6.7.7, “Cloning for Replication”。

提示

要部署多个 MySQL 实例,可以使用 InnoDB Cluster,它使您能够轻松管理一组 MySQL 服务器实例在 MySQL Shell 中。InnoDB Cluster 在一个编程环境中包装了 MySQL Group Replication,使您可以轻松部署一组 MySQL 实例以实现高可用性。此外,InnoDB Cluster 与 MySQL Router 无缝接口,使您的应用程序可以连接到集群而无需编写自己的故障转移过程。然而,对于不需要高可用性的类似用例,您可以使用 InnoDB ReplicaSet。有关 MySQL Shell 的安装说明,请参见此处。

19.1.2.5.1 使用 mysqldump 创建数据快照

要在现有源数据库中创建数据快照,请使用mysqldump工具。完成数据转储后,在启动复制过程之前将这些数据导入副本。

以下示例将所有数据库转储到名为dbdump.db的文件中,并包括–master-data选项,该选项会自动附加在副本上启动复制过程所需的CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句:

$> mysqldump –all-databases –master-data > dbdump.db

注意

如果不使用–master-data,则需要在单独的会话中手动锁定所有表。参见 Section 19.1.2.4, “Obtaining the Replication Source Binary Log Coordinates”。

可以使用mysqldump工具排除转储中的某些数据库。如果要选择要包含在转储中的数据库,请不要使用–all-databases。选择以下选项之一:

使用–ignore-table选项排除数据库中的所有表。
只命名要转储的数据库,使用–databases选项。

注意

默认情况下,如果源端使用 GTIDs(gtid_mode=ON),mysqldump 在转储输出中包含源端gtid_executed集合中的 GTIDs,以将其添加到副本端的gtid_purged集合中。如果只转储特定数据库或表,重要的是要注意,mysqldump 包含的值包括源端gtid_executed集合中的所有事务的 GTIDs,即使这些事务更改了数据库的被抑制部分,或者服务器上的其他未包含在部分转储中的数据库。查看 mysqldump 的–set-gtid-purged选项的描述,以找到您正在使用的 MySQL 服务器版本的默认行为结果,以及如何更改行为,如果此结果不适合您的情况。

有关更多信息,请参阅 Section 6.5.4, “mysqldump — A Database Backup Program”。

要导入数据,可以将转储文件复制到副本,或者在远程连接到副本时从源文件访问。

19.1.2.5.2 使用原始数据文件创建数据快照

本节描述了如何使用组成数据库的原始文件创建数据快照。使用这种方法时,对于使用具有复杂缓存或日志算法的存储引擎的表,需要额外的步骤来生成完美的“时间点”快照:初始复制命令可能会遗漏缓存信息和日志更新,即使你已经获得了全局读锁。存储引擎对此的响应取决于其崩溃恢复能力。

如果使用InnoDB表,可以使用 MySQL Enterprise Backup 组件中的mysqlbackup命令生成一致的快照。该命令记录了与要在副本上使用的快照对应的日志名称和偏移量。MySQL Enterprise Backup 是作为 MySQL Enterprise 订阅的一部分包含的商业产品。详细信息请参见 Section 32.1, “MySQL Enterprise Backup Overview”。

这种方法在源和副本具有不同值ft_stopword_file、ft_min_word_len或ft_max_word_len时也无法可靠工作,如果你要复制具有全文索引的表。

假设上述例外情况不适用于你的数据库,使用冷备份技术获取InnoDB表的可靠二进制快照:对 MySQL Server 进行慢关闭,然后手动复制数据文件。

当你的 MySQL 数据文件存在于单个文件系统上时,可以使用标准文件复制工具如cp或copy,远程复制工具如scp或rsync,压缩工具如zip或tar,或文件系统快照工具如dump来创建MyISAM表的原始数据快照。如果只复制特定数据库,只复制与这些表相关的文件。对于InnoDB,除非启用了innodb_file_per_table选项,否则所有数据库中的所有表都存储在系统表空间文件中。

以下文件不需要用于复制:

与mysql数据库相关的文件。
副本的连接元数据存储库文件master.info,如果使用;现在已弃用此文件的使用(参见 Section 19.2.4, “Relay Log and Replication Metadata Repositories”)。
源的二进制日志文件,除非您打算使用它来定位副本的源二进制日志坐标时,不包括二进制日志索引文件。
任何中继日志文件。

根据您是否使用InnoDB表,选择以下操作之一:

如果您正在使用InnoDB表,并且为了获得最一致的原始数据快照结果,请在过程中关闭源服务器,具体操作如下:

获取读锁并获取源的状态。参见第 19.1.2.4 节,“获取复制源二进制日志坐标”。
在单独的会话中,关闭源服务器:
$> mysqladmin shutdown
复制 MySQL 数据文件。以下示例展示了常见的操作方式。您只需选择其中一种:
$> tar cf */tmp/db.tar* *./data*
$> zip -r */tmp/db.zip* *./data*
$> rsync –recursive *./data* */tmp/dbdata*
重新启动源服务器。

如果您没有使用InnoDB表,您可以从源获取系统快照而无需关闭服务器,具体步骤如下:

获取读锁并获取源的状态。参见第 19.1.2.4 节,“获取复制源二进制日志坐标”。
复制 MySQL 数据文件。以下示例展示了常见的操作方式。您只需选择其中一种:
$> tar cf */tmp/db.tar* *./data*
$> zip -r */tmp/db.zip* *./data*
$> rsync –recursive *./data* */tmp/dbdata*
在获取读锁的客户端中,释放锁:
mysql> UNLOCK TABLES;

创建数据库的归档或副本后,在启动复制过程之前将文件复制到每个副本。

原文:dev.mysql.com/doc/refman/8.0/en/replication-setup-replicas.html

19.1.2.6 设置副本

以下各节描述了如何设置副本。在继续之前,请确保您已经:

配置了具有必要配置属性的源。请参阅 Section 19.1.2.1, “设置复制源配置”。
获取源状态信息,或在数据快照期间关闭时制作源的二进制日志索引文件的副本。请参阅 Section 19.1.2.4, “获取复制源二进制日志坐标”。
在源上释放读锁:
mysql> UNLOCK TABLES;
在副本上编辑了 MySQL 配置。请参阅 Section 19.1.2.2, “设置副本配置”。

接下来的步骤取决于您是否有要导入到副本的现有数据。有关更多信息,请参阅 Section 19.1.2.5, “选择数据快照方法”。选择以下之一:

如果没有要导入的数据库快照,请参阅 Section 19.1.2.6.1, “使用新源和副本设置复制”。
如果您有要导入的数据库快照,请参阅 Section 19.1.2.6.2, “使用现有数据设置复制”。

19.1.2.6.1 使用新源和副本设置复制

如果没有以前数据库的快照要导入,请配置副本以从新源开始复制。

要在源和新副本之间设置复制:

启动副本。
在副本上执行CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句,设置源配置。请参阅 Section 19.1.2.7, “在副本上设置源配置”。

在每个副本上执行以下副本设置步骤。

如果您正在设置新服务器,但有来自不同服务器的现有数据库转储,想要加载到您的复制配置中,也可以使用此方法。通过将数据加载到新源,数据会自动复制到副本。

如果您正在使用来自不同现有数据库服务器的数据创建新源来设置新的复制环境,请在新源上运行从该服务器生成的转储文件。数据库更新会自动传播到副本:

$> mysql -h source < fulldb.dump

19.1.2.6.2 使用现有数据设置复制

在使用现有数据设置复制时,在开始复制之前,将快照从源传输到副本。将数据导入副本的过程取决于您如何在源上创建数据的快照。

提示

要部署多个 MySQL 实例,您可以使用 InnoDB Cluster,它使您能够轻松管理一组 MySQL 服务器实例在 MySQL Shell 中。InnoDB Cluster 在一个编程环境中封装了 MySQL Group Replication,使您可以轻松部署一组 MySQL 实例以实现高可用性。此外,InnoDB Cluster 与 MySQL Router 无缝接口,使您的应用程序可以连接到集群而无需编写自己的故障转移过程。然而,对于不需要高可用性的类似用例,您可以使用 InnoDB ReplicaSet。有关 MySQL Shell 的安装说明,请参见这里。

注意

如果要复制的复制源服务器或现有副本在创建新副本时有任何计划事件,请确保在启动新副本之前将其禁用。如果新副本上运行的事件已在源上运行,则重复的操作会导致错误。事件调度程序由event_scheduler系统变量控制,默认情况下从 MySQL 8.0 开始为ON,因此在新副本启动时默认情况下会运行在原始服务器上活动的事件。要停止新副本上的所有事件运行,请将event_scheduler系统变量设置为OFF或DISABLED。或者,您可以使用ALTER EVENT语句将单独的事件设置为DISABLE或DISABLE ON SLAVE以防止它们在新副本上运行。您可以使用SHOW语句或信息模式EVENTS表列出服务器上的事件。有关更多信息,请参见 Section 19.5.1.16, “Replication of Invoked Features”。

作为在这种方式下创建新副本的替代方案,MySQL Server 的克隆插件可以用于将所有数据和复制设置从现有副本传输到克隆中。有关使用此方法的说明,请参见 Section 7.6.7.7, “复制用于克隆”。

按照以下步骤设置使用现有数据的复制:

如果您使用 MySQL Server 的克隆插件从现有副本创建克隆(参见 Section 7.6.7.7, “复制用于克隆”),则数据已经传输。否则,使用以下方法之一将数据导入到副本中。

如果您使用了mysqldump,启动副本服务器,确保使用–skip-slave-start选项或从 MySQL 8.0.24 开始,使用skip_slave_start系统变量来防止复制启动。然后导入转储文件:
$> mysql < fulldb.dump
如果您使用原始数据文件创建快照,请将数据文件提取到副本的数据目录中。例如:
$> tar xvf dbdump.tar
您可能需要设置文件的权限和所有权,以便副本服务器可以访问和修改它们。然后启动副本服务器,确保使用–skip-slave-start选项或从 MySQL 8.0.24 开始,使用skip_slave_start系统变量来防止复制启动。
使用源的复制坐标配置副本。这告诉副本需要开始复制的二进制日志文件和文件内位置。还要使用源的登录凭据和主机名配置副本。有关所需的CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句的更多信息,请参见 Section 19.1.2.7, “在副本上设置源配置”。
通过发出START REPLICA(或在 MySQL 8.0.22 之前,START SLAVE)语句来启动复制线程。

完成此过程后,副本将连接到源并复制自快照以来在源上发生的任何更新。如果由于任何原因副本无法复制,则会向副本的错误日志发出错误消息。

复制品使用其连接元数据存储库和应用程序元数据存储库中记录的信息来跟踪已处理源二进制日志的数量。从 MySQL 8.0 开始,默认情况下,这些存储库是mysql数据库中名为slave_master_info和slave_relay_log_info的表。除非您确切知道自己在做什么并完全了解其影响,否则不要删除或编辑这些表。即使在这种情况下,最好使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句来更改复制参数。复制品使用语句中指定的值来自动更新复制元数据存储库。有关更多信息,请参见第 19.2.4 节,“中继日志和复制元数据存储库”。

注意

复制品的连接元数据存储库的内容会覆盖在命令行或my.cnf中指定的一些服务器选项。详细信息请参见第 19.1.6 节,“复制和二进制日志选项和变量”。

源的单个快照足以供多个复制品使用。要设置额外的复制品,请使用相同的源快照,并按照刚才描述的复制品部分的步骤进行操作。

原文:dev.mysql.com/doc/refman/8.0/en/replication-howto-slaveinit.html

19.1.2.7 在副本上设置源配置

要设置副本与源通信以进行复制,请使用必要的连接信息配置副本。为此,在副本上执行CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前),将选项值替换为与您系统相关的实际值:

mysql> CHANGE MASTER TO
-> MASTER_HOST=\’*source_host_name*\’,
-> MASTER_USER=\’*replication_user_name*\’,
-> MASTER_PASSWORD=\’*replication_password*\’,
-> MASTER_LOG_FILE=\’*recorded_log_file_name*\’,
-> MASTER_LOG_POS=*recorded_log_position*;
Or from MySQL 8.0.23:
mysql> CHANGE REPLICATION SOURCE TO
-> SOURCE_HOST=\’*source_host_name*\’,
-> SOURCE_USER=\’*replication_user_name*\’,
-> SOURCE_PASSWORD=\’*replication_password*\’,
-> SOURCE_LOG_FILE=\’*recorded_log_file_name*\’,
-> SOURCE_LOG_POS=*recorded_log_position*;

注意

复制不能使用 Unix 套接字文件。您必须能够使用 TCP/IP 连接到源 MySQL 服务器。

CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句还有其他选项。例如,可以使用 SSL 设置安全复制。有关选项的完整列表以及有关字符串值选项的最大允许长度的信息,请参阅第 15.4.2.1 节“CHANGE MASTER TO Statement”。

重要提示

如第 19.1.2.3 节“为复制创建用户”中所述,如果您未使用安全连接,并且SOURCE_USER | MASTER_USER选项中指定的用户帐户使用caching_sha2_password插件进行身份验证(从 MySQL 8.0 开始的默认设置),则必须在CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句中指定SOURCE_PUBLIC_KEY_PATH | MASTER_PUBLIC_KEY_PATH或GET_SOURCE_PUBLIC_KEY | GET_MASTER_PUBLIC_KEY选项,以启用基于 RSA 密钥对的密码交换。

原文:dev.mysql.com/doc/refman/8.0/en/replication-howto-additionalslaves.html

19.1.2.8 向复制环境添加复制实例

您可以在不停止源服务器的情况下向现有复制配置中添加另一个复制实例。为此,您可以通过复制现有复制实例的数据目录来设置新的复制实例,并为新的复制实例指定不同的服务器 ID(由用户指定)和服务器 UUID(在启动时生成)。

注意

如果您要复制以创建新的复制实例的复制源服务器或现有复制实例具有任何计划事件,请确保在启动新的复制实例之前将这些事件禁用。如果新的复制实例上运行的事件已经在源上运行过,则重复的操作会导致错误。事件调度程序由event_scheduler系统变量控制,默认情况下从 MySQL 8.0 开始为ON,因此在新的复制实例启动时默认情况下会运行在原始服务器上活动的事件。要停止新的复制实例上的所有事件运行,请在新的复制实例上将event_scheduler系统变量设置为OFF或DISABLED。或者,您可以使用ALTER EVENT语句将单个事件设置为DISABLE或DISABLE ON SLAVE以防止它们在新的复制实例上运行。您可以使用SHOW语句或信息模式EVENTS表列出服务器上的事件。有关更多信息,请参见 Section 19.5.1.16, “Replication of Invoked Features”。

作为以这种方式创建新的复制实例的替代方法,MySQL 服务器的克隆插件可用于将所有数据和复制设置从现有复制实例传输到克隆实例。有关使用此方法的说明,请参见 Section 7.6.7.7, “Cloning for Replication”。

要复制现有的复制实例而不进行克隆,请按照以下步骤操作:

停止现有的复制实例并记录复制实例状态信息,特别是源二进制日志文件和中继日志文件位置。您可以通过性能模式复制表(请参阅 Section 29.12.11, “Performance Schema Replication Tables”)查看复制实例状态,或通过以下方式发出SHOW REPLICA STATUS:
mysql> STOP SLAVE;
mysql> SHOW SLAVE STATUS\\G
Or from MySQL 8.0.22:
mysql> STOP REPLICA;
mysql> SHOW REPLICA STATUS\\G
关闭现有的复制实例:
$> mysqladmin shutdown
将现有副本的数据目录复制到新副本,包括日志文件和中继日志文件。您可以通过使用tar或WinZip创建存档,或者通过使用cp或rsync等工具执行直接复制来完成此操作。
重要

在复制之前,请验证所有与现有副本相关的文件实际上是否存储在数据目录中。例如,InnoDB系统表空间、撤消表空间和重做日志可能存储在其他位置。InnoDB表空间文件和文件表空间可能已在其他目录中创建。副本的二进制日志和中继日志可能在数据目录之外的自己的目录中。检查为现有副本设置的系统变量,并查找是否已指定任何替代路径。如果找到任何内容,请将这些目录一并复制过去。
在复制过程中,如果文件用于复制元数据存储库(请参阅第 19.2.4 节,“中继日志和复制元数据存储库”),请确保还将这些文件从现有副本复制到新副本。如果表用于存储库,这是从 MySQL 8.0 开始的默认设置,则这些表位于数据目录中。
复制后,从新副本的数据目录副本中删除auto.cnf文件,以便新副本使用不同生成的服务器 UUID 启动。服务器 UUID 必须是唯一的。
添加新副本时遇到的常见问题是,新副本失败,并显示一系列警告和错误消息,例如:
071118 16:44:10 [Warning] Neither –relay-log nor –relay-log-index were used; so
replication may break when this MySQL server acts as a replica and has his hostname
changed!! Please use \’–relay-log=*new_replica_hostname*-relay-bin\’ to avoid this problem.
071118 16:44:10 [ERROR] Failed to open the relay log \’./*old_replica_hostname*-relay-bin.003525\’
(relay_log_pos 22940879)
071118 16:44:10 [ERROR] Could not find target log during relay log initialization
071118 16:44:10 [ERROR] Failed to initialize the master info structure
如果未指定relay_log系统变量,则可能会出现此情况,因为中继日志文件的文件名中包含主机名。如果未使用relay_log_index系统变量,则中继日志索引文件也是如此。有关这些变量的更多信息,请参见第 19.1.6 节,“复制和二进制日志选项和变量”。
为避免此问题,在新的复制品上使用与现有复制品上使用的relay_log相同的值。如果在现有复制品上未显式设置此选项,请使用*existing_replica_hostname*-relay-bin。如果不可能,请将现有复制品的中继日志索引文件复制到新的复制品,并将新的复制品上的relay_log_index系统变量设置为与现有复制品上使用的相匹配。如果在现有复制品上未显式设置此选项,请使用*existing_replica_hostname*-relay-bin.index。或者,如果您在按照本节中的其余步骤后已尝试启动新的复制品并遇到类似先前描述的错误,则执行以下步骤:

如果您尚未这样做,请在新的复制品上发出STOP REPLICA。
如果您已经重新启动了现有的复制品,请在现有的复制品上也发出STOP REPLICA。
将现有复制品的中继日志索引文件的内容复制到新复制品的中继日志索引文件中,确保覆盖文件中已有的任何内容。
继续执行本节中的其余步骤。
复制完成后,重新启动现有复制品。
在新的复制品上,编辑配置并为新的复制品分配一个不被源或任何现有复制品使用的唯一服务器 ID(使用server_id系统变量)。
启动新的复制服务器,确保通过指定–skip-slave-start选项或从 MySQL 8.0.24 开始,使用skip_slave_start系统变量,确保复制尚未开始。使用性能模式复制表或发出SHOW REPLICA STATUS来确认新的复制品与现有复制品相比是否具有正确的设置。还要显示服务器 ID 和服务器 UUID,并验证这些对于新的复制品是正确且唯一的。
通过发出START REPLICA语句来启动复制线程。新的复制品现在使用其连接元数据存储库中的信息来启动复制过程。

19.1.3 具有全局事务标识符的复制

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

19.1.3.1 GTID 格式和存储

19.1.3.2 GTID 生命周期

19.1.3.3 GTID 自动定位

19.1.3.4 使用 GTID 设置复制

19.1.3.5 使用 GTID 进行故障切换和扩展

19.1.3.6 从没有 GTID 的源复制到具有 GTID 的副本

19.1.3.7 GTID 复制限制

19.1.3.8 用于操作 GTID 的存储函数示例

本节解释了使用全局事务标识符(GTID)进行基于事务的复制。使用 GTID 时,每个事务都可以在原始服务器上提交时进行标识和跟踪,并由任何副本应用;这意味着在使用 GTID 时,不需要在启动新副本或故障切换到新源时引用日志文件或文件内的位置,这极大地简化了这些任务。由于基于 GTID 的复制完全基于事务,因此很容易确定源和副本是否一致;只要在源上提交的所有事务也在副本上提交,就可以保证两者之间的一致性。您可以使用基于语句或基于行的复制与 GTID(参见第 19.2.1 节,“复制格式”);但是,为了获得最佳结果,我们建议您使用基于行的格式。

GTID 在源和副本之间始终保留。这意味着您始终可以通过检查其二进制日志来确定任何副本上应用的任何事务的源。此外,一旦在给定服务器上提交具有特定 GTID 的事务,该服务器将忽略具有相同 GTID 的任何后续事务。因此,在源上提交的事务在副本上最多只能应用一次,这有助于保证一致性。

本节讨论以下主题:

GTID 的定义和创建方式,以及它们在 MySQL 服务器中的表示方式(参见第 19.1.3.1 节,“GTID 格式和存储”)。
GTID 的生命周期(参见第 19.1.3.2 节,“GTID 生命周期”)。
用于同步使用 GTID 的副本和源的自动定位功能(参见第 19.1.3.3 节,“GTID 自动定位”)。
设置和启动基于 GTID 的复制的一般流程(参见第 19.1.3.4 节,“使用 GTIDs 设置复制”)。
在使用 GTIDs 时为新复制服务器提供建议的方法(参见第 19.1.3.5 节,“在故障转移和扩展中使用 GTIDs”)。
使用 GTID-based 复制时应注意的限制和限制(参见第 19.1.3.7 节,“使用 GTIDs 进行复制的限制”)。
存储函数可用于处理 GTIDs(参见第 19.1.3.8 节,“用于操作 GTIDs 的存储函数示例”)。

有关与 GTID-based 复制相关的 MySQL 服务器选项和变量的信息,请参见第 19.1.6.5 节,“全局事务 ID 系统变量”。另请参阅第 14.18.2 节,“与全局事务标识符(GTIDs)一起使用的函数”\”),其中描述了 MySQL 8.0 支持用于 GTIDs 的 SQL 函数。

原文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-concepts.html

19.1.3.1 GTID 格式和存储

全局事务标识符(GTID)是在源服务器上(源)提交的每个事务创建并关联的唯一标识符。该标识符不仅对于其起源的服务器是唯一的,而且在给定复制拓扑结构中的所有服务器上都是唯一的。

GTID 分配区分了客户端事务(在源上提交)和复制事务(在副本上重现)。当客户端事务在源上提交时,如果事务已写入二进制日志,则会分配一个新的 GTID。客户端事务保证具有单调递增的 GTID,生成的数字之间没有间隙。如果客户端事务未写入二进制日志(例如,因为事务被过滤掉,或者事务是只读的),则在源服务器上不会分配 GTID。

复制事务保留在源服务器上分配给事务的相同 GTID。GTID 在复制事务开始执行之前存在,并且即使在副本上未将复制事务写入二进制日志或在副本上被过滤掉,也会持久存在。MySQL 系统表 mysql.gtid_executed 用于保留应用于 MySQL 服务器上的所有事务的分配 GTID,除了那些存储在当前活动二进制日志文件中的事务。

GTID 的自动跳过功能意味着在源上提交的事务在副本上最多只能应用一次,这有助于保证一致性。一旦具有特定 GTID 的事务在给定服务器上提交,那么该服务器将忽略执行具有相同 GTID 的后续事务的任何尝试。不会引发错误,也不会执行事务中的任何语句。

如果具有特定 GTID 的事务已经在服务器上开始执行,但尚未提交或回滚,则在服务器上尝试启动具有相同 GTID 的并发事务会被阻塞。服务器既不开始执行并发事务,也不将控制权返回给客户端。一旦第一次尝试的事务提交或回滚,那些在相同 GTID 上阻塞的并发会话可以继续。如果第一次尝试回滚,一个并发会话将继续尝试事务,而任何其他在相同 GTID 上阻塞的并发会话将保持阻塞。如果第一次尝试提交,所有并发会话将停止被阻塞,并自动跳过事务的所有语句。

GTID 表示为一对坐标,用冒号字符(:)分隔,如下所示:

GTID = *source_id*:*transaction_id*

source_id 标识了来源服务器。通常,使用源的 server_uuid 来实现此目的。transaction_id 是由事务在源上提交的顺序确定的序列号。例如,第一个提交的事务的 transaction_id 为 1,在同一来源服务器上提交的第十个事务被分配一个 transaction_id 为 10。在 GTID 中,事务不可能具有 0 作为序列号。例如,在具有 UUID 3E11FA47-71CA-11E1-9E33-C80AA9429562 的服务器上最初提交的第二十三个事务具有以下 GTID:

3E11FA47-71CA-11E1-9E33-C80AA9429562:23

服务器实例上 GTID 的序列号上限是有符号 64 位整数的非负值数量(2 的 63 次方减 1,即 9,223,372,036,854,775,807)。如果服务器用尽了 GTID,将执行 binlog_error_action 中指定的操作。从 MySQL 8.0.23 开始,当服务器实例接近限制时会发出警告消息。

事务的 GTID 在 mysqlbinlog 的输出中显示,并用于在性能模式复制状态表中标识单个事务,例如 replication_applier_status_by_worker。gtid_next 系统变量 (@@GLOBAL.gtid_next) 存储的是单个 GTID。

GTID 集合

一个 GTID 集合由一个或多个单个 GTID 或 GTID 范围组成。在 MySQL 服务器中,GTID 集合有多种用途。例如,gtid_executed 和 gtid_purged 系统变量存储的值就是 GTID 集合。START REPLICA(或 MySQL 8.0.22 之前的 START SLAVE)子句 UNTIL SQL_BEFORE_GTIDS 和 UNTIL SQL_AFTER_GTIDS 可以用来使复制进程仅处理 GTID 集合中第一个 GTID 之前的事务,或在 GTID 集合中最后一个 GTID 之后停止。内置函数 GTID_SUBSET() 和 GTID_SUBTRACT() 需要 GTID 集合作为输入。

来自同一服务器的一系列 GTID 可以合并为一个表达式,如下所示:

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5

上述示例代表了在 MySQL 服务器上起源的第一到第五个事务,其server_uuid为3E11FA47-71CA-11E1-9E33-C80AA9429562。来自同一服务器的多个单个 GTID 或 GTID 范围也可以包含在单个表达式中,GTID 或范围之间用冒号分隔,如下例所示:

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3:11:47-49

GTID 集可以包含任意组合的单个 GTID 和 GTID 范围,并且可以包含来自不同服务器的 GTID。此示例显示了存储在副本的gtid_executed系统变量(@@GLOBAL.gtid_executed)中的 GTID 集,该副本已应用来自多个来源的事务:

2174B383-5441-11E8-B90A-C80AA9429562:1-3, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19

当从服务器变量返回 GTID 集时,UUID 按字母顺序排列,数字间隔被合并并按升序排列。

GTID 集的语法如下:

*gtid_set*:
*uuid_set* [, *uuid_set*] …
| \’\’
*uuid_set*:
*uuid*:*interval*[:*interval*]…
*uuid*:
*hhhhhhhh*-*hhhh*-*hhhh*-*hhhh*-*hhhhhhhhhhhh*
*h*:
[0-9|A-F]
*interval*:
*n*[-*n*]
(*n* >= 1)

mysql.gtid_executed 表

GTIDs 存储在名为gtid_executed的表中,位于mysql数据库中。此表中的一行包含每个 GTID 或其代表的 GTID 集的起始服务器的 UUID,以及集合的起始和结束事务 ID;对于仅引用单个 GTID 的行,这两个值相同。

当安装或升级 MySQL 服务器时,将创建(如果尚不存在)mysql.gtid_executed表,使用类似于以下所示的CREATE TABLE语句:

CREATE TABLE gtid_executed (
source_uuid CHAR(36) NOT NULL,
interval_start BIGINT(20) NOT NULL,
interval_end BIGINT(20) NOT NULL,
PRIMARY KEY (source_uuid, interval_start)
)

警告

与其他 MySQL 系统表一样,请不要尝试自行创建或修改此表。

mysql.gtid_executed表供 MySQL 服务器内部使用。当在副本上禁用二进制日志记录时,它使副本能够使用 GTIDs,并在二进制日志丢失时保留 GTID 状态。请注意,如果发出RESET MASTER命令,mysql.gtid_executed表将被清除。

仅当gtid_mode为ON或ON_PERMISSIVE时,GTIDs 才存储在mysql.gtid_executed表中。如果二进制日志记录已禁用(log_bin为OFF),或者如果log_replica_updates或log_slave_updates已禁用,则服务器将每个事务的 GTID 与事务一起存储在缓冲区中提交事务时,并且后台线程定期将缓冲区的内容作为一个或多个条目添加到mysql.gtid_executed表中。此外,表会定期以用户可配置的速率进行压缩,如 mysql.gtid_executed 表压缩中所述。

如果启用了二进制日志记录(log_bin为ON),从 MySQL 8.0.17 开始,仅适用于InnoDB存储引擎,服务器会在事务提交时以与禁用二进制日志记录或复制更新日志相同的方式更新mysql.gtid_executed表,存储每个事务的 GTID。然而,在 MySQL 8.0.17 之前的版本中,以及对于其他存储引擎,服务器仅在二进制日志轮换或服务器关闭时更新mysql.gtid_executed表。在这些时候,服务器会将之前二进制日志中写入的所有事务的 GTID 写入mysql.gtid_executed表。这种情况适用于 MySQL 8.0.17 之前的源端,或者在启用二进制日志记录的 MySQL 8.0.17 之前的复制端,或者使用除InnoDB之外的存储引擎,它具有以下后果:

在服务器意外停止的情况下,当前二进制日志文件中的 GTID 集合不会保存在mysql.gtid_executed表中。这些 GTID 在恢复过程中从二进制日志文件中添加到表中,以便复制可以继续进行。唯一的例外是,如果在服务器重新启动时禁用了二进制日志记录(使用–skip-log-bin或–disable-log-bin)。在这种情况下,服务器无法访问二进制日志文件以恢复 GTID,因此无法启动复制。
mysql.gtid_executed表不包含所有已执行事务的 GTID 的完整记录。这些信息由全局值gtid_executed系统变量提供。在 MySQL 8.0.17 之前的版本和使用除InnoDB之外的存储引擎时,始终使用@@GLOBAL.gtid_executed,该值在每次提交后更新,以表示 MySQL 服务器的 GTID 状态,而不是查询mysql.gtid_executed表。

MySQL 服务器在只读或超级只读模式下仍可以写入mysql.gtid_executed表。在 MySQL 8.0.17 之前的版本中,这确保了在这些模式下仍然可以旋转二进制日志文件。如果无法访问mysql.gtid_executed表进行写入,并且二进制日志文件因其他原因而旋转(而不是达到最大文件大小max_binlog_size),则继续使用当前的二进制日志文件。向请求旋转的客户端返回错误消息,并在服务器上记录警告。如果无法访问mysql.gtid_executed表进行写入,并且达到max_binlog_size,则服务器根据其binlog_error_action设置做出响应。如果设置为IGNORE_ERROR,则在服务器上记录错误并停止二进制日志记录,或者如果设置为ABORT_SERVER,则服务器关闭。

mysql.gtid_executed 表压缩

随着时间的推移,mysql.gtid_executed表可能会填满许多行,这些行引用在同一服务器上起源的单个 GTID,并且其事务 ID 组成一个范围,类似于这里显示的内容:

+————————————–+—————-+————–+
| source_uuid | interval_start | interval_end |
|————————————–+—————-+————–|
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37 | 37 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 38 | 38 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 39 | 39 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 40 | 40 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 41 | 41 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 42 | 42 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 43 | 43 |

为节省空间,MySQL 服务器可以定期压缩mysql.gtid_executed表,通过用跨越整个事务标识符间隔的单行替换每个这样的行集,如下所示:

+————————————–+—————-+————–+
| source_uuid | interval_start | interval_end |
|————————————–+—————-+————–|
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37 | 43 |

服务器可以使用名为thread/sql/compress_gtid_table的专用前台线程执行压缩。此线程不在SHOW PROCESSLIST的输出中列出,但可以在threads表中查看,如下所示:

mysql> SELECT * FROM performance_schema.threads WHERE NAME LIKE \’%gtid%\’\\G
*************************** 1\\. row ***************************
THREAD_ID: 26
NAME: thread/sql/compress_gtid_table
TYPE: FOREGROUND
PROCESSLIST_ID: 1
PROCESSLIST_USER: NULL
PROCESSLIST_HOST: NULL
PROCESSLIST_DB: NULL
PROCESSLIST_COMMAND: Daemon
PROCESSLIST_TIME: 1509
PROCESSLIST_STATE: Suspending
PROCESSLIST_INFO: NULL
PARENT_THREAD_ID: 1
ROLE: NULL
INSTRUMENTED: YES
HISTORY: YES
CONNECTION_TYPE: NULL
THREAD_OS_ID: 18677

当服务器启用二进制日志记录时,不使用此压缩方法,而是在每次二进制日志旋转时压缩mysql.gtid_executed表。但是,当服务器禁用二进制日志记录时,thread/sql/compress_gtid_table线程会休眠,直到执行了指定数量的事务,然后唤醒以压缩mysql.gtid_executed表。然后再休眠,直到发生相同数量的事务,然后再次唤醒以执行压缩,无限循环。在表被压缩之前经过的事务数量,因此压缩速率,由gtid_executed_compression_period系统变量的值控制。将该值设置为 0 意味着线程永远不会唤醒,这意味着不使用此显式压缩方法。相反,根据需要隐式进行压缩。

从 MySQL 8.0.17 开始,InnoDB 事务由一个独立进程写入到mysql.gtid_executed表,与非InnoDB事务分开。这个进程由不同的线程innodb/clone_gtid_thread控制。这个 GTID 持久化线程将 GTID 分组收集,将它们刷新到mysql.gtid_executed表,然后压缩表格。如果服务器同时有InnoDB事务和非InnoDB事务,它们分别写入到mysql.gtid_executed表,那么compress_gtid_table线程执行的压缩会干扰 GTID 持久化线程的工作,并且可能显著减慢速度。因此,从那个版本开始,建议将gtid_executed_compression_period设置为 0,这样compress_gtid_table线程就永远不会被激活。

从 MySQL 8.0.23 开始,gtid_executed_compression_period的默认值为 0,InnoDB和非InnoDB事务都由 GTID 持久化线程写入到mysql.gtid_executed表。

对于 MySQL 8.0.17 之前的版本,默认值为 1000 的gtid_executed_compression_period可以使用,意味着每 1000 个事务后对表进行压缩,或者您可以选择另一个值。在这些版本中,如果将值设置为 0 且禁用了二进制日志记录,则不会对mysql.gtid_executed表执行显式压缩,如果这样做,您应该准备好表可能需要的磁盘空间可能会大幅增加。

当启动服务器实例时,如果gtid_executed_compression_period设置为非零值并且启动了thread/sql/compress_gtid_table线程,在大多数服务器配置中,将为mysql.gtid_executed表执行显式压缩。在 MySQL 8.0.17 之前的版本中,启用二进制日志时,压缩是由于启动时二进制日志轮换触发的。在 MySQL 8.0.20 之后的版本中,压缩是由线程启动触发的。在这些版本之间的版本中,启动时不会进行压缩。

译文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-lifecycle.html

19.1.3.2 GTID 生命周期

GTID 的生命周期包括以下步骤:

事务在源端执行并提交。此客户端事务被分配一个由源的 UUID 和尚未在此服务器上使用的最小非零事务序列号组成的 GTID。GTID 被写入源的二进制日志(在日志中的事务之前立即写入)。如果客户端事务未写入二进制日志(例如,因为事务被过滤掉,或者事务是只读的),则不会分配 GTID。
如果为事务分配了 GTID,则在提交时通过将其写入二进制日志的方式原子地持久化该 GTID(作为 Gtid_log_event)。每当二进制日志被轮换或服务器关闭时,服务器将为写入到上一个二进制日志文件中的所有事务写入 GTID 到 mysql.gtid_executed 表中。
如果为事务分配了 GTID,则在事务提交后不久通过将其添加到 gtid_executed 系统变量 (@@GLOBAL.gtid_executed) 中的 GTID 集合来非原子化地外部化该 GTID。此 GTID 集合包含所有已提交 GTID 事务的表示,并且在复制中用作表示服务器状态的令牌。启用二进制日志记录(源端所需)后,gtid_executed 系统变量中的 GTID 集合是应用的所有事务的完整记录,但 mysql.gtid_executed 表不是,因为最近的历史仍在当前二进制日志文件中。
在二进制日志数据传输到副本并存储在副本的中继日志中(使用已建立的机制进行此过程,详见第 19.2 节,“复制实现”),副本读取 GTID 并将其设置为其 gtid_next 系统变量的值。这告诉副本下一个事务必须使用此 GTID 记录。重要的是要注意,副本在会话上下文中设置 gtid_next。
副本验证尚未有任何线程拥有gtid_next中的 GTID 以处理事务。通过首先读取和检查复制的事务的 GTID,然后再处理事务本身,副本确保不仅在副本上未应用具有此 GTID 的先前事务,而且也没有其他会话已经读取此 GTID 但尚未提交关联事务。因此,如果多个客户端尝试并发应用相同的事务,服务器通过只允许其中一个执行来解决此问题。副本的gtid_owned系统变量(@@GLOBAL.gtid_owned)显示当前正在使用的每个 GTID 及拥有它的线程的 ID。如果 GTID 已经被使用,不会引发错误,并且自动跳过功能用于忽略该事务。
如果 GTID 尚未被使用,副本将应用复制的事务。因为gtid_next已设置为源已分配的 GTID,副本不会尝试为此事务生成新的 GTID,而是使用存储在gtid_next中的 GTID。
如果副本上启用了二进制日志记录,GTID 将在提交时以原子方式持久化,通过在事务开始时将其写入二进制日志(作为Gtid_log_event)。每当二进制日志轮换或服务器关闭时,服务器将为之前写入的所有事务写入的 GTID 写入mysql.gtid_executed表。
如果副本上禁用了二进制日志记录,则通过直接将其写入mysql.gtid_executed表来以原子方式持久化 GTID。MySQL 会向事务追加一个语句,将 GTID 插入表中。从 MySQL 8.0 开始,对于 DDL 语句以及 DML 语句,此操作都是原子的。在这种情况下,mysql.gtid_executed表是副本上应用的事务的完整记录。
在副本上提交的事务后不久,GTID 将通过将其添加到副本的gtid_executed系统变量(@@GLOBAL.gtid_executed)中的 GTID 集合中非原子化地外部化。对于源,此 GTID 集合包含所有已提交 GTID 事务集合的表示。如果副本上禁用了二进制日志记录,则mysql.gtid_executed表也是副本上应用的事务的完整记录。如果副本上启用了二进制日志记录,意味着某些 GTID 仅记录在二进制日志中,则gtid_executed系统变量中的 GTID 集合是唯一的完整记录。

在源端完全被过滤掉的客户端事务不会被分配 GTID,因此它们不会被添加到gtid_executed系统变量的事务集合中,也不会被添加到mysql.gtid_executed表中。然而,在副本上完全被过滤掉的复制事务的 GTID 会被保留。如果在副本上启用了二进制日志记录,被过滤掉的事务会被写入二进制日志作为一个Gtid_log_event,然后是一个只包含BEGIN和COMMIT语句的空事务。如果禁用了二进制日志记录,被过滤掉的事务的 GTID 会被写入mysql.gtid_executed表中。保留被过滤掉事务的 GTID 确保了mysql.gtid_executed表和gtid_executed系统变量中的 GTID 集合可以被压缩。它还确保了如果副本重新连接到源端,被过滤掉的事务不会再次被检索,如第 19.1.3.3 节“GTID 自动定位”中所解释的那样。

在多线程副本(具有replica_parallel_workers > 0或slave_parallel_workers > 0)上,事务可以并行应用,因此复制事务可以无序提交(除非设置了replica_preserve_commit_order=1或slave_preserve_commit_order=1)。当发生这种情况时,gtid_executed系统变量中的 GTID 集合包含多个 GTID 范围之间的间隙。(在源端或单线程副本上,GTID 是单调递增的,数字之间没有间隙。)多线程副本上的间隙仅出现在最近应用的事务之间,并且随着复制的进行而填补。当使用STOP REPLICA语句干净地停止复制线程时,正在进行的事务会被应用,以便填补间隙。在发生诸如服务器故障或使用KILL语句停止复制线程等关闭事件时,这些间隙可能会保留。

哪些更改会被分配一个 GTID?

典型情况是服务器为已提交的事务生成一个新的 GTID。然而,除了事务之外,GTIDs 也可以分配给其他更改,并且在某些情况下,单个事务可以被分配多个 GTIDs。

每个写入二进制日志的数据库更改(DDL 或 DML)都被分配一个 GTID。这包括自动提交的更改,以及使用BEGIN和COMMIT或START TRANSACTION语句提交的更改。GTID 也分配给数据库的创建、修改或删除,以及非表数据库对象(如存储过程、函数、触发器、事件、视图、用户、角色或授权)。

非事务更新以及事务更新都被分配 GTID。此外,对于非事务更新,如果在尝试写入二进制日志缓存时发生磁盘写入失败,从而在二进制日志中创建了一个间隙,那么生成的事件日志事件将被分配一个 GTID。

当一个表被二进制日志中的生成语句自动删除时,该语句被分配一个 GTID。当一个复制开始应用来自刚刚启动的源的事件时,临时表会被自动删除,并且当使用基于语句的复制(binlog_format=STATEMENT)并且一个具有打开临时表的用户会话断开连接时。使用MEMORY存储引擎的表在服务器启动后第一次访问时会自动删除,因为在关闭期间可能会丢失行。

当一个事务在原始服务器上没有写入二进制日志时,服务器不会为其分配 GTID。这包括被回滚的事务和在原始服务器上禁用二进制日志记录时执行的事务,无论是全局禁用(在服务器配置中指定–skip-log-bin)还是对会话禁用(SET @@SESSION.sql_log_bin = 0)。当使用基于行的复制时(binlog_format=ROW),这也包括无操作事务。

XA 事务为事务的XA PREPARE阶段和XA COMMIT或XA ROLLBACK阶段分配单独的 GTID。XA 事务被持久准备,以便用户在失败的情况下(在复制拓扑中可能包括故障转移到另一台服务器)提交或回滚它们。因此,事务的两个部分被分别复制,因此它们必须有自己的 GTID,即使一个被回滚的非 XA 事务不会有 GTID。

在以下特殊情况下,单个语句可以生成多个事务,因此被分配多个 GTID:

调用了提交多个事务的存储过程。为存储过程提交的每个事务生成一个 GTID。
一个多表DROP TABLE语句会删除不同类型的表。如果任何表使用不支持原子 DDL 的存储引擎,或者任何表是临时表,可能会生成多个 GTID。
当使用基于行的复制(binlog_format=ROW)时,会发出CREATE TABLE … SELECT语句。为CREATE TABLE操作生成一个 GTID,并为行插入操作生成一个 GTID。

gtid_next系统变量

默认情况下,在用户会话中提交的新事务,服务器会自动生成并分配新的 GTID。在副本上应用事务时,会保留来自原始服务器的 GTID。您可以通过设置gtid_next系统变量的会话值来更改此行为:

当gtid_next设置为AUTOMATIC时,这是默认值,事务提交并写入二进制日志时,服务器会自动生成并分配新的 GTID。如果事务回滚或由于其他原因未写入二进制日志,则服务器不会生成和分配 GTID。
如果将gtid_next设置为有效的 GTID(由 UUID 和事务序列号组成,用冒号分隔),服务器会将该 GTID 分配给您的事务。即使事务未写入二进制日志,或者事务为空,此 GTID 也会被分配并添加到gtid_executed。

请注意,在将gtid_next设置为特定 GTID 后,事务已提交或回滚后,必须在任何其他语句之前发出显式的SET @@SESSION.gtid_next语句。如果不想显式分配更多 GTID,则可以使用此方法将 GTID 值设置回AUTOMATIC。

当复制应用程序线程应用复制事务时,它们使用这种技术,将@@SESSION.gtid_next显式设置为在原始服务器上分配的复制事务的 GTID。这意味着来自原始服务器的 GTID 被保留,而不是由副本生成和分配新的 GTID。这也意味着即使在副本上禁用了二进制日志记录或副本更新日志,或者事务是无操作或在副本上被过滤掉,GTID 也会被添加到gtid_executed。

客户端可以通过将@@SESSION.gtid_next设置为特定的 GTID 来模拟一个复制事务,然后执行该事务。这种技术被mysqlbinlog用于生成客户端可以重放以保留 GTID 的二进制日志转储。通过客户端提交的模拟复制事务与通过复制应用程序线程提交的复制事务完全等效,在事后无法区分它们。

gtid_purged系统变量

gtid_purged系统变量(@@GLOBAL.gtid_purged)中包含了在服务器上已提交但不存在于服务器上任何二进制日志文件中的所有事务的 GTID。gtid_purged是gtid_executed的子集。gtid_purged中包含以下类别的 GTID:

在副本上禁用二进制日志记录的复制事务的 GTID。
被写入二进制日志文件并已被清除的事务的 GTID。
通过语句SET @@GLOBAL.gtid_purged显式添加到集合中的 GTID。

您可以更改gtid_purged的值,以记录在服务器上已应用某个 GTID 集的事务,尽管这些事务在服务器上的任何二进制日志中都不存在。当您将 GTID 添加到gtid_purged时,它们也会被添加到gtid_executed中。执行此操作的一个示例用例是,当您在服务器上恢复一个或多个数据库的备份时,但您没有包含服务器上事务的相关二进制日志。在 MySQL 8.0 之前,只有在gtid_executed(因此也是gtid_purged)为空时才能更改gtid_purged的值。从 MySQL 8.0 开始,不再有此限制,您还可以选择是否用指定的 GTID 集替换gtid_purged中的整个 GTID 集,或者将指定的 GTID 集添加到已在gtid_purged中的 GTID 中。有关如何执行此操作的详细信息,请参阅gtid_purged的描述。

当服务器启动时,gtid_executed 和 gtid_purged 系统变量中的 GTID 集合在初始化时被初始化。每个二进制日志文件都以事件Previous_gtids_log_event开头,其中包含了所有先前二进制日志文件中的 GTIDs 集合(由前一个文件的Previous_gtids_log_event中的 GTIDs 和前一个文件中每个Gtid_log_event的 GTIDs 组成)。最老和最近的二进制日志文件中的Previous_gtids_log_event的内容用于计算服务器启动时的gtid_executed 和 gtid_purged 集合:

gtid_executed 是由最近的二进制日志文件中的Previous_gtids_log_event中的 GTIDs、该二进制日志文件中的事务的 GTIDs 以及mysql.gtid_executed表中存储的 GTIDs 的并集计算而得。这个 GTID 集合包含了服务器上已经使用过的 GTIDs(或者明确添加到gtid_purged中的 GTIDs),无论它们当前是否在服务器上的二进制日志文件中。它不包括当前在服务器上处理的事务的 GTIDs(@@GLOBAL.gtid_owned)。
gtid_purged 首先通过将最近的二进制日志文件中的Previous_gtids_log_event中的 GTIDs 和该二进制日志文件中的事务的 GTIDs 相加来计算。这一步给出了当前或曾经在服务器上的二进制日志中记录的 GTIDs 集合(gtids_in_binlog)。接下来,从最老的二进制日志文件中的Previous_gtids_log_event中减去gtids_in_binlog中的 GTIDs。这一步给出了当前在服务器上的二进制日志中记录的 GTIDs 集合(gtids_in_binlog_not_purged)。最后,从gtid_executed中减去gtids_in_binlog_not_purged。结果是在服务器上已经使用过的 GTIDs 集合,但当前没有在服务器上的二进制日志文件中记录,这个结果用于初始化gtid_purged。

如果涉及来自 MySQL 5.7.7 或更早版本的二进制日志在这些计算中,可能会计算出gtid_executed和gtid_purged的不正确 GTID 集,并且即使稍后重新启动服务器,它们仍然不正确。有关详细信息,请参阅binlog_gtid_simple_recovery系统变量的描述,该变量控制如何迭代二进制日志以计算 GTID 集。如果服务器上适用于其中描述的情况之一,请在启动服务器之前在服务器的配置文件中设置binlog_gtid_simple_recovery=FALSE。该设置使服务器迭代所有二进制日志文件(而不仅仅是最新和最旧的)以查找 GTID 事件开始出现的位置。如果服务器有大量没有 GTID 事件的二进制日志文件,这个过程可能需要很长时间。

重置 GTID 执行历史

如果需要在服务器上重置 GTID 执行历史,请使用RESET MASTER语句。例如,在新的 GTID 启用服务器上执行测试查询以验证复制设置,或者当您想要将新服务器加入到复制组中但它包含一些不被组复制接受的不需要的本地事务时,可能需要执行此操作。

警告

谨慎使用RESET MASTER,以避免丢失任何需要的 GTID 执行���史和二进制日志文件。

在执行RESET MASTER之前,请确保已备份服务器的二进制日志文件和二进制日志索引文件(如果有),并获取并保存gtid_executed系统变量的全局值中保存的 GTID 集(例如,通过执行SELECT @@GLOBAL.gtid_executed语句并保存结果)。如果要从该 GTID 集中删除不需要的事务,请使用mysqlbinlog检查事务的内容,以确保它们没有价值,不包含必须保存或复制的数据,并且不会导致服务器上的数据更改。

当您执行RESET MASTER时,将执行以下重置操作:

gtid_purged系统变量的值被设置为空字符串(\’\’)。
全局值(但不是会话值)的gtid_executed系统变量被设置为空字符串。
mysql.gtid_executed 表被清空(参见 mysql.gtid_executed Table)。
如果服务器启用了二进制日志记录,则现有的二进制日志文件将被删除,二进制日志索引文件将被清空。

请注意,RESET MASTER 是重置 GTID 执行历史记录的方法,即使服务器是一个禁用二进制日志记录的副本。RESET REPLICA 对 GTID 执行历史记录没有影响。

原文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-auto-positioning.html

19.1.3.3 GTID 自动定位

GTID 取代了以前需要确定源和副本之间数据流开始、停止或恢复点的文件偏移对。当使用 GTID 时,副本与源同步所需的所有信息都直接从复制数据流中获取。

要使用基于 GTID 的复制启动副本,需要在 CHANGE REPLICATION SOURCE TO 语句(从 MySQL 8.0.23 开始)或 CHANGE MASTER TO 语句(MySQL 8.0.23 之前)中启用 SOURCE_AUTO_POSITION | MASTER_AUTO_POSITION 选项。另外的 SOURCE_LOG_FILE | MASTER_LOG_FILE 和 SOURCE_LOG_POS | MASTER_LOG_POS 选项指定了日志文件的名称和文件内的起始位置,但是使用 GTID 时,副本不需要这些非本地数据。有关使用基于 GTID 的复制配置和启动源和副本的完整说明,请参见 Section 19.1.3.4, “Setting Up Replication Using GTIDs”。

SOURCE_AUTO_POSITION | MASTER_AUTO_POSITION 选项默认情况下是禁用的。如果在副本上启用了多源复制,则需要为每个适用的复制通道设置该选项。再次禁用 SOURCE_AUTO_POSITION | MASTER_AUTO_POSITION 选项会导致副本恢复到基于位置的复制;这意味着当 GTID_ONLY=ON 时,某些位置可能被标记为无效,在这种情况下,当禁用 SOURCE_AUTO_POSITION | MASTER_AUTO_POSITION 时,还必须同时指定 SOURCE_LOG_FILE | MASTER_LOG_FILE 和 SOURCE_LOG_POS | MASTER_LOG_POS。

当副本启用了 GTIDs(GTID_MODE=ON,ON_PERMISSIVE或OFF_PERMISSIVE)并启用了MASTER_AUTO_POSITION选项时,自动定位将被激活以连接到源端。源端必须设置GTID_MODE=ON才能成功连接。在初始握手中,副本发送一个包含其已经接收、提交或两者都有的交易的 GTID 集合。这个 GTID 集合等于gtid_executed系统变量(@@GLOBAL.gtid_executed)中的 GTID 集合和性能模式中记录的 GTID 集合的并集,性能模式中的 GTID 集合是作为已接收交易记录的(执行SELECT RECEIVED_TRANSACTION_SET FROM PERFORMANCE_SCHEMA.replication_connection_status语句的结果)。

源端通过发送其二进制日志中记录的所有交易来响应,这些交易的 GTID 不包含在副本发送的 GTID 集合中。为此,源端首先通过检查其二进制日志文件的头部中的Previous_gtids_log_event来确定要开始处理的适当二进制日志文件,从最近的文件开始检查。当源端找到第一个不包含副本缺失交易的Previous_gtids_log_event时,它就从那个二进制日志文件开始。这种方法是高效的,只有在副本落后源端很多个二进制日志文件时才会花费大量时间。然后,源端读取该二进制日志文件和后续文件中的交易,直到当前文件,发送副本缺失的带有 GTID 的交易,并跳过副本发送的 GTID 集合中的交易。副本接收到第一个缺失交易的经过时间取决于其在二进制日志文件中的偏移量。这种交换确保源端只发送副本尚未接收或提交的带有 GTID 的交易。如果副本从多个源接收交易,如钻石拓扑结构的情况下,自动跳过功能确保交易不会被应用两次。

如果应该由源发送的任何事务已经从源的二进制日志中清除,或者通过其他方法添加到gtid_purged系统变量的 GTID 集合中,源会向副本发送错误ER_MASTER_HAS_PURGED_REQUIRED_GTIDS,并且复制不会启动。缺失的已清除事务的 GTID 将在源的错误日志中被识别并列在警告消息ER_FOUND_MISSING_GTIDS中。副本无法自动从此错误中恢复,因为需要追赶源的事务历史的部分已被清除。尝试重新连接而没有启用MASTER_AUTO_POSITION选项只会导致副本上的已清除事务的丢失。从这种情况中恢复的正确方法是让副本从另一个源复制ER_FOUND_MISSING_GTIDS消息中列出的缺失事务,或者让副本被一个从更近期备份创建的新副本所取代。考虑修改源上的二进制日志过期时间(binlog_expire_logs_seconds)以确保不再发生这种情况。

如果在交换事务过程中发现复制品已经收到或提交了具有源 GTID 中 UUID 的事务,但源本身没有记录它们,源会向复制品发送错误ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER,复制不会开始。如果源没有设置sync_binlog=1并遇到断电或操作系统崩溃,且丢失了尚未同步到二进制日志文件的已提交事务,但已被复制品接收,那么就会出现这种情况。如果在源重新启动后有任何客户端提交事务,可能导致源和复制品使用相同的 GTID 进行不同的事务,源和复制品可能会发散。从这种情况中恢复的正确方法是手动检查源和复制品是否发散。如果现在对不同事务使用相同的 GTID,则需要根据需要对单个事务执行手动冲突解决,或者从复制拓扑中删除源或复制品。如果问题仅在源上缺少事务,则可以将源变为复制品,使其赶上复制拓扑中的其他服务器,然后根据需要再次将其变为源。

对于钻石拓扑结构中的多源复制(其中复制品从两个或更多源复制,这些源又从一个共同源复制),当使用基于 GTID 的复制时,请确保多源复制上的所有通道上的任何复制过滤器或其他通道配置都是相同的。使用基于 GTID 的复制时,过滤器仅应用于事务数据,而 GTID 不会被过滤掉。这是为了使复制品的 GTID 集与源保持一致,这意味着可以使用 GTID 自动定位而无需每次重新获取被过滤的事务。在下游复制品是多源的情况下,并且在钻石拓扑结构中从多个源接收相同事务的情况下,下游复制品现在具有事务的多个版本,结果取决于哪个通道首先应用该事务。尝试的第二个通道通过使用 GTID 自动跳过来跳过该事务,因为该事务的 GTID 已被第一个通道添加到gtid_executed集中。在通道上具有相同过滤器的情况下,没有问题,因为所有事务的所有版本都包含相同的数据,因此结果是相同的。然而,在通道上具有不同过滤器的情况下,数据库可能变得不一致,复制可能会挂起。

原文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-howto.html

19.1.3.4 使用 GTID 设置复制

本节描述了在 MySQL 8.0 中配置和启动基于 GTID 的复制的过程。这是一个“冷启动”过程,假设您要么是第一次启动源服务器,要么可以停止它;有关从运行中的源服务器使用 GTID 为副本提供服务的信息,请参阅第 19.1.3.5 节,“使用 GTID 进行故障转移和扩展”。有关在线更改服务器上的 GTID 模式的信息,请参阅第 19.1.4 节,“在线更改 GTID 模式”。

最简单的 GTID 复制拓扑结构的启动过程中的关键步骤,包括一个源和一个副本,如下所示:

如果复制已经在运行,请使两个服务器变为只读状态以进行同步。
停止两个服务器。
使用启用了 GTID 并配置了正确选项的正确选项重新启动两个服务器。
启动服务器所需的mysqld选项将在本节稍后的示例中讨论。
指示副本使用源作为复制数据源并使用自动定位。完成此步骤所需的 SQL 语句在本节稍后的示例中描述。
进行新的备份。包含没有 GTID 的事务的二进制日志不能在启用 GTID 的服务器上使用,因此在此点之前进行的备份不能与新配置一起使用。
启动副本,然后在两个服务器上禁用只读模式,以便它们可以接受更新。

在以下示例中,两个服务器已经作为源和副本运行,使用 MySQL 的基于二进制日志位置的复制协议。如果您要使用新服务器,请参阅第 19.1.2.3 节,“为复制创建用户”以获取有关为复制连接添加特定用户的信息,以及第 19.1.2.1 节,“设置复制源配置”以获取有关设置server_id变量的信息。以下示例显示了如何在服务器的选项文件中存储mysqld启动选项,请参阅第 6.2.2.2 节,“使用选项文件”以获取更多信息。或者,您可以在运行mysqld时使用启动选项。

后续大部分步骤需要使用 MySQL root 帐户或具有SUPER权限的其他 MySQL 用户帐户。mysqladmin shutdown 需要SUPER权限或SHUTDOWN权限。

第一步:同步服务器。 仅在使用不使用 GTID 复制的服务器时才需要此步骤。对于新服务器,请继续到第三步。通过在每个服务器上将read_only系统变量设置为ON来使服务器只读,发出以下命令:

mysql> SET @@GLOBAL.read_only = ON;

等待所有正在进行的事务提交或回滚。然后,允许复制品赶上源。确保复制品处理了所有更新非常重要。

如果您使用二进制日志来进行除了复制之外的任何操作,例如进行时点备份和恢复,请等到您不再需要包含没有 GTID 的旧二进制日志。理想情况下,等待服务器清除所有二进制日志,并等待任何现有备份过期。

重要提示

重要提示:必须了解不包含 GTID 的事务的日志不能在启用 GTID 的服务器上使用。在继续之前,您必须确保在拓扑结构中任何地方都不存在不带 GTID 的事务。

第二步:停止两个服务器。 使用mysqladmin停止每个服务器,如下所示,其中*username*是具有足够权限关闭服务器的 MySQL 用户的用户名:

$> mysqladmin -u*username* -p shutdown

然后在提示处提供此用户的密码。

第三步:启用两个启用 GTID 的服务器。 要启用基于 GTID 的复制,必须通过将gtid_mode变量设置为ON来启用每个服务器的 GTID 模式,并通过启用enforce_gtid_consistency变量来确保仅记录对于基于 GTID 的复制安全的语句。例如:

gtid_mode=ON
enforce-gtid-consistency=ON

使用 –skip-slave-start 选项或从 MySQL 8.0.24 开始,使用 skip_slave_start 系统变量,确保在配置副本设置之前不会启动复制。从 MySQL 8.0.26 开始,改用 –skip-replica-start 或 skip_replica_start。有关 GTID 相关选项和变量的更多信息,请参见 第 19.1.6.5 节,“全局事务 ID 系统变量”。

在使用 mysql.gtid_executed 表 时,不需要启用二进制日志记录才能使用 GTIDs 是强制性的。源服务器必须始终启用二进制日志记录才能进行复制。但是,副本服务器可以使用 GTIDs,但不启用二进制日志记录。如果需要在副本服务器上禁用二进制日志记录,可以通过为副本指定 –skip-log-bin 和 –log-replica-updates=OFF 或 –log-slave-updates=OFF 选项来实现。

第 4 步:配置副本以使用基于 GTID 的自动定位。 告诉副本使用具有基于 GTID 的事务的源作为复制数据源,并使用基于 GTID 的自动定位而不是基于文件的定位。在副本上发出 CHANGE REPLICATION SOURCE TO 语句(从 MySQL 8.0.23 开始)或 CHANGE MASTER TO 语句(在 MySQL 8.0.23 之前),在语句中包含 SOURCE_AUTO_POSITION | MASTER_AUTO_POSITION 选项,告诉副本源的事务由 GTIDs 标识。

您可能还需要为源主机名和端口号以及用于副本连接到源的复制用户帐户的用户名和密码提供适当的值;如果这些值在第 1 步之前已经设置并且不需要进行进一步更改,则可以安全地从此处显示的语句中省略相应的选项。

mysql> CHANGE MASTER TO
> MASTER_HOST = *host*,
> MASTER_PORT = *port*,
> MASTER_USER = *user*,
> MASTER_PASSWORD = *password*,
> MASTER_AUTO_POSITION = 1;
Or from MySQL 8.0.23:
mysql> CHANGE REPLICATION SOURCE TO
> SOURCE_HOST = *host*,
> SOURCE_PORT = *port*,
> SOURCE_USER = *user*,
> SOURCE_PASSWORD = *password*,
> SOURCE_AUTO_POSITION = 1;

第 5 步:进行新的备份。 在启用 GTIDs 之前制作的现有备份现在无法在这些服务器上使用,因为您已经启用了 GTIDs。在这一点上进行新的备份,这样您就不会没有可用的备份了。

例如,您可以在执行备份的服务器上执行FLUSH LOGS。然后要么明确地进行备份,要么等待您设置的任何定期备份例程的下一次迭代。

步骤 6:启动副本并禁用只读模式。 像这样启动副本:

mysql> START SLAVE;
Or from MySQL 8.0.22:
mysql> START REPLICA;

如果您在第 1 步中将服务器配置为只读,则需要执行以下步骤才能使服务器再次接受更新。发出以下语句:

mysql> SET @@GLOBAL.read_only = OFF;

基于 GTID 的复制现在应该正在运行,您可以像以前一样开始(或恢复)源上的活动。第 19.1.3.5 节,“使用 GTIDs 进行故障转移和扩展”,讨论了在使用 GTIDs 时创建新副本。

译文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-failover.html

19.1.3.5 使用 GTIDs 进行故障切换和扩展

在使用带有全局事务标识符(GTIDs)的 MySQL 复制时,有许多技术可用于为新副本提供数据,然后用于扩展,必要时提升为源以进行故障切换。本节描述以下技术:

简单复制
将数据和事务复制到副本
注入空事务
排除具有 gtid_purged 的事务
恢复 GTID 模式副本

全局事务标识符被添加到 MySQL 复制中,目的是简化复制数据流的管理以及特定情况下的故障切换活动。每个标识符唯一标识一组二进制日志事件,这些事件一起构成一个事务。GTIDs 在应用对数据库的更改中起着关键作用:服务器会自动跳过任何具有服务器识别为其之前已处理过的标识符的事务。这种行为对于自动复制定位和正确的故障切换至关重要。

标识符与构成给定事务的事件集之间的映射被记录在二进制日志中。当为新服务器提供来自另一个现有服务器的数据时,这会带来一些挑战。为了在新服务器上复制标识符集,需要将标识符从旧服务器复制到新服务器,并保留标识符与实际事件之间的关系。这对于恢复一个立即可用作故障切换或切换源的副本是必要的。

简单复制。 在新服务器上复制所有标识符和事务的最简单方法是将新服务器制作为具有完整执行历史记录的源的副本,并在两个服务器上启用全局事务标识符。有关更多信息,请参见 Section 19.1.3.4, “使用 GTIDs 设置复制”。

一旦复制开始,新服务器会从源服务器复制整个二进制日志,从而获取所有关于所有 GTIDs 的信息。

这种方法简单而有效,但需要副本从源读取二进制日志;新副本有时可能需要相对较长的时间才能赶上源,因此此方法不适用于快速故障转移或从备份中恢复。本节解释了如何通过将二进制日志文件复制到新服务器来避免从源获取所有执行历史记录。

将数据和事务复制到副本。 当源服务器之前处理了大量事务时,执行整个事务历史记录可能会耗时,这在设置新副本时可能会成为一个主要瓶颈。为了消除这一要求,可以将源服务器包含的数据集、二进制日志和全局事务信息的快照导入到新副本中。快照被拍摄的服务器可以是源服务器或其副本之一,但必须确保服务器在复制数据之前已处理了所有必需的事务。

有几种这种方法的变体,其区别在于从二进制日志中转移数据转储和事务到副本的方式,如下所述:

数据集

在源服务器上使用mysqldump创建一个转储文件。设置mysqldump选项–master-data(默认值为 1)以包含带有二进制日志信息的CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句。将–set-gtid-purged选项设置为AUTO(默认)或ON,以在转储中包含有关已执行事务的信息。然后使用mysql客户端在目标服务器上导入转储文件。
或者,使用原始数据文件在源服务器上创建数据快照,然后将这些文件复制到目标服务器,按照第 19.1.2.5 节,“选择数据快照方法”中的说明进行操作。如果使用InnoDB表,可以使用 MySQL Enterprise Backup 组件中的mysqlbackup命令生成一致的快照。该命令记录了与快照对应的日志名称和偏移量,以便在副本上使用。MySQL Enterprise Backup 是 MySQL Enterprise 订阅的一部分,是一款商业产品。详细信息请参见第 32.1 节,“MySQL Enterprise Backup 概述”。
或者,停止源服务器和目标服务器,将源数据目录的内容复制到新副本的数据目录,然后重新启动副本。如果使用此方法,副本必须配置为基于 GTID 的复制,换句话说,使用 gtid_mode=ON。有关此方法的说明和重要信息,请参见 第 19.1.2.8 节“将副本添加到复制环境”。

事务历史

如果源服务器在其二进制日志中具有完整的事务历史记录(即,GTID 集 @@GLOBAL.gtid_purged 为空),则可以使用这些方法。

使用 mysqlbinlog 将源服务器的二进制日志导入新副本,使用 –read-from-remote-server、–read-from-remote-source 和 –read-from-remote-master 选项。
或者,将源服务器的二进制日志文件复制到副本。您可以使用 mysqlbinlog 从副本中复制,使用 –read-from-remote-server 和 –raw 选项。这些可以通过使用 mysqlbinlog > *file*(不使用 –raw 选项)将二进制日志文件导出到 SQL 文件,然后将这些文件传递给 mysql 客户端进行处理。确保所有二进制日志文件都使用单个 mysql 进程处理,而不是多个连接。例如:
$> mysqlbinlog copied-binlog.000001 copied-binlog.000002 | mysql -u root -p
有关更多信息,请参见 第 6.6.9.3 节“使用 mysqlbinlog 备份二进制日志文件”。

这种方法的优势在于几乎立即可以获得新服务器;只有在重放快照或转储文件时提交的交易才需要从现有源获取。这意味着副本的可用性并非即时,但只需要相对较短的时间即可使副本赶上这些少量剩余交易。

预先复制二进制日志到目标服务器通常比实时从源读取整个事务执行历史要快。然而,当需要时,将这些文件移动到目标可能并不总是可行,由于大小或其他考虑。本节讨论的用于为新副本配置的另外两种方法使用其他方式将有关事务的信息传输到新副本。

注入空事务。 源的全局gtid_executed变量包含在源上执行的所有事务的集合。在拍摄快照以为新服务器配置时,您可以在拍摄快照的服务器上记录gtid_executed的内容,而不是复制二进制日志。在将新服务器添加到复制链之前,只需为源的gtid_executed中包含的每个事务标识符在新服务器上提交一个空事务,就像这样:

SET GTID_NEXT=\’aaa-bbb-ccc-ddd:N\’;
BEGIN;
COMMIT;
SET GTID_NEXT=\’AUTOMATIC\’;

一旦所有事务标识符都通过使用空事务重新建立,您必须刷新并清除副本的二进制日志,如下所示,其中*N*是当前二进制日志文件名的非零后缀:

FLUSH LOGS;
PURGE BINARY LOGS TO \’source-bin.00000*N*\’;

您应该这样做,以防止该服务器在以后被提升为源时通过虚假事务淹没复制流。(FLUSH LOGS语句强制创建一个新的二进制日志文件;PURGE BINARY LOGS清除空事务,但保留它们的标识符。)

这种方法创建了一个本质上是快照的服务器,但随着其二进制日志历史与复制流的收敛(即,与源或源的收敛),它能够成为一个源。这种结果在效果上类似于使用剩余的配置方法获得的效果,我们将在接下来的几段中讨论。

排除具有 gtid_purged 的事务。 源的全局gtid_purged 变量包含已从源的二进制日志中清除的所有事务的集合。与之前讨论的方法一样(参见注入空事务),您可以记录从快照被取得的服务器上的gtid_executed 的值(而不是将二进制日志复制到新服务器)。与以前的方法不同,无需提交空事务(或发出PURGE BINARY LOGS);相反,您可以根据从备份或快照被取得的服务器上的gtid_executed 的值,在复制品上直接设置gtid_purged。

与使用空事务的方法一样,此方法创建了一个在功能上是快照的服务器,但随着其二进制日志历史与源和其他复制品的收敛,它可以成为一个源。

恢复 GTID 模式的复制品。 在遇到错误的基于 GTID 的复制设置中恢复复制品时,注入空事务可能无法解决问题,因为事件没有 GTID。

使用 mysqlbinlog 查找下一个事务,这可能是事件后下一个日志文件中的第一个事务。复制直到该事务的COMMIT,确保包括SET @@SESSION.gtid_next。即使您不使用基于行的复制,也可以在命令行客户端中运行二进制日志行事件。

停止复制品并运行您复制的事务。mysqlbinlog 输出将分隔符设置为/*!*/;,因此将其设置回去:

mysql> DELIMITER ;

自动从正确位置重新启动复制:

mysql> SET GTID_NEXT=automatic;
mysql> RESET SLAVE;
mysql> START SLAVE;
Or from MySQL 8.0.22:
mysql> SET GTID_NEXT=automatic;
mysql> RESET REPLICA;
mysql> START REPLICA;

原文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-assign-anon.html

19.1.3.6 从没有 GTIDs 的源到具有 GTIDs 的复制品的复制

从 MySQL 8.0.23 开始,您可以设置复制通道以为尚未具有 GTID 的复制事务分配 GTID。此功能使得可以从未启用 GTIDs 并且不使用基于 GTID 的复制的源服务器复制到启用了 GTIDs 的复制品。如果可以在复制源服务器上启用 GTIDs,如第 19.1.4 节“在线更改 GTID 模式”中所述,请使用该方法。此功能适用于无法启用 GTIDs 的复制源服务器。请注意,与 MySQL 复制的标准相同,此功能不支持从 MySQL 源服务器复制到先前发布系列之前的 MySQL 源服务器,因此 MySQL 5.7 是 MySQL 8.0 复制品的最早支持源。

您可以使用CHANGE REPLICATION SOURCE TO语句的ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS选项在复制通道上启用 GTID 分配。LOCAL分配一个包括复制品自身 UUID(server_uuid设置)的 GTID。*uuid*分配一个包括指定 UUID 的 GTID,例如复制源服务器的server_uuid设置。使用非本地 UUID 可以区分在复制品上发起的事务和在源上发起的事务,以及在多源复制品上,区分在不同源上发起的事务。如果源发送的任何事务已经有 GTID,则保留该 GTID。

重要提示

在任何通道上设置了ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS的复制品无法在需要故障转移时晋升为替换复制源服务器,并且无法使用从复制品备份的备份来恢复复制源服务器。替换或恢复其他使用任何通道上的ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS的复制品也适用相同的限制。

复制品必须设置gtid_mode=ON,且此后不能更改,除非删除ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS=ON设置。如果复制品服务器在未启用 GTIDs 的情况下启动,并为任何复制通道设置了ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS,则设置不会更改,但会向错误日志写入警告消息,解释如何更改情况。

对于多源复制品,您可以混合使用使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS和不使用的通道。专用于组复制的通道不能使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS,但是在作为组复制组成员的服务器实例上的另一个源的异步复制通道可以这样做。对于组复制组成员上的通道,请不要将组复制组名称指定为创建 GTID 的 UUID。

在复制通道上使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS并不等同于为通道引入基于 GTID 的复制。使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS设置的复制品的 GTID 集合(gtid_executed)不应传输到另一台服务器或与另一台服务器的gtid_executed集合进行比较。分配给匿名事务的 GTID 以及您为其选择的 UUID 仅对该复制品自身的使用具有意义。唯一的例外是启用了ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS的复制品的任何下游复制品,以及从该复制品的备份创建的任何服务器。

如果您设置了任何下游复制品,这些服务器不会启用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS。只有直接从非 GTID 源服务器接收事务的复制品需要在相关复制通道上设置ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS。在该复制品及其下游复制品之间,您可以比较 GTID 集合,从一个复制品故障转移至另一个复制品,并使用备份创建额外的复制品,就像在任何基于 GTID 的复制拓扑中一样。ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS用于从此组外部的非 GTID 服务器接收事务的情况。

使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS的复制通道与基于 GTID 的复制有以下行为差异:

当应用复制的事务时,将为其分配 GTID(除非它们已经有 GTID)。通常,当事务提交时,GTID 会在复制源服务器上分配,并与事务一起发送到复制品。在多线程复制品上,这意味着 GTID 的顺序不一定与事务的顺序匹配,即使设置了slave-preserve-commit-order=1。
CHANGE REPLICATION SOURCE TO语句的SOURCE_LOG_FILE和SOURCE_LOG_POS选项用于定位复制 I/O(接收器)线程,而不是SOURCE_AUTO_POSITION选项。
使用SET GLOBAL sql_replica_skip_counter或SET GLOBAL sql_slave_skip_counter语句跳过使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS设置的复制通道上的事务,而不是提交空事务的方法。有关说明,请参见 Section 19.1.7.3, “Skipping Transactions”。
START REPLICA语句的UNTIL SQL_BEFORE_GTIDS和UNTIL_SQL_AFTER_GTIDS选项不能用于通道。
函数WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()在 MySQL 8.0.18 中已被弃用,不能与通道一起使用。它的替代品WAIT_FOR_EXECUTED_GTID_SET()可以在整个服务器上工作,可用于等待启用了ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS的服务器的任何下游复制品。要等待启用了ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS的通道赶上不使用 GTIDs 的源,请使用SOURCE_POS_WAIT()函数(从 MySQL 8.0.26 开始)或MASTER_POS_WAIT()函数。

Performance Schema replication_applier_configuration 表显示复制通道上是否为匿名事务分配了 GTIDs,UUID 是什么,以及它是副本服务器的 UUID(LOCAL)还是用户指定的 UUID(UUID)。这些信息也记录在 applier 元数据存储库中。RESET REPLICA ALL语句会重置ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS设置,但RESET REPLICA语句不会。

原文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-restrictions.html

19.1.3.7 GTID 复制的限制

因为基于 GTID 的复制依赖于事务,所以在使用时不支持 MySQL 中其他可用的一些功能。本节提供有关使用 GTID 进行复制的限制和限制的信息。

涉及非事务性存储引擎的更新。 在使用 GTID 时,对使用非事务性存储引擎(如MyISAM)的表进行更新不能与对使用事务性存储引擎(如InnoDB)的表进行更新在同一语句或事务中进行。

这个限制是因为在同一事务中对使用非事务性存储引擎的表进行更新与对使用事务性存储引擎的表进行更新可能导致将多个 GTID 分配给同一事务。

当源和副本为相同表的不同版本使用不同的存储引擎时,可能会出现这些问题,其中一个存储引擎是事务性的,另一个不是。还要注意,对非事务表进行操作的触发器可能是这些问题的原因。

在上述任何情况下,事务和 GTID 之间的一对一对应关系被打破,导致基于 GTID 的复制无法正常运行。

CREATE TABLE … SELECT 语句。 在 MySQL 8.0.21 之前,当使用基于 GTID 的复制时,不允许使用 CREATE TABLE … SELECT 语句。当 binlog_format 设置为 STATEMENT 时,CREATE TABLE … SELECT 语句在二进制日志中记录为一个具有一个 GTID 的事务,但如果使用 ROW 格式,则该语句将记录为具有两个 GTID 的两个事务。如果源使用 STATEMENT 格式,副本使用 ROW 格式,则副本将无法正确处理事务,因此为了防止这种情况,不允许使用 GTID 的 CREATE TABLE … SELECT 语句。在支持原子 DDL 的存储引擎上,此限制在 MySQL 8.0.21 中解除。在这种情况下,CREATE TABLE … SELECT 在二进制日志中记录为一个事务。有关更多信息,请参见 Section 15.1.1, “原子数据定义语句支持”。

临时表。 当binlog_format设置为STATEMENT时,在服务器上使用 GTIDs 时(即当enforce_gtid_consistency系统变量设置为ON时),不能在事务、存储过程、函数和触发器中使用CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE语句。当使用 GTIDs 时,可以在这些上下文之外使用它们,前提是设置了autocommit=1。从 MySQL 8.0.13 开始,当binlog_format设置为ROW或MIXED时,在使用 GTIDs 时,可以在事务、存储过程、函数或触发器中使用CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE语句。这些语句不会写入二进制日志,因此不会被复制到副本。使用基于行的复制意味着副本保持同步,无需复制临时表。如果从事务中删除这些语句导致事务为空,该事务不会写入二进制日志。

阻止执行不支持的语句。 为防止导致基于 GTID 的复制失败的语句执行,启用 GTIDs 时必须在所有服务器上使用–enforce-gtid-consistency选项启动。这将导致本节前面讨论的任何类型的语句执行失败并显示错误。

请注意,只有在为语句启用二进制日志记录时,–enforce-gtid-consistency才会生效。如果服务器上禁用了二进制日志记录,或者如果语句未写入二进制日志因为它们被过滤器移除,那么对于未记录的语句,GTID 一致性不会被检查或强制执行。

有关启用 GTIDs 时其他必需的启动选项的信息,请参阅 Section 19.1.3.4, “Setting Up Replication Using GTIDs”。

跳过事务。 当使用基于 GTID 的复制时,sql_replica_skip_counter或sql_slave_skip_counter不可用。如果需要跳过事务,请使用源的gtid_executed变量的值。如果已经在复制通道上启用了 GTID 分配,使用CHANGE REPLICATION SOURCE TO语句的ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS选项,则sql_replica_skip_counter或sql_slave_skip_counter是可用的。更多信息,请参见第 19.1.7.3 节,“跳过事务”。

忽略服务器。 在使用 GTIDs 时,CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句的 IGNORE_SERVER_IDS 选项已被弃用,因为已经应用的事务会自动被忽略。在开始基于 GTID 的复制之前,请检查并清除之前在涉及的服务器上设置的所有被忽略的服务器 ID 列表。可以为单个通道发出的SHOW REPLICA STATUS语句显示被忽略的服务器 ID 列表(如果有)。如果没有列表,则Replicate_Ignore_Server_Ids字段为空。

GTID 模式和 mysql_upgrade。 在 MySQL 8.0.16 之前,当服务器启用全局事务标识符(GTIDs)(gtid_mode=ON)时,请不要通过mysql_upgrade(–write-binlog选项)启用二进制日志记录。从 MySQL 8.0.16 开始,服务器执行整个 MySQL 升级过程,但在升级过程中禁用二进制日志记录,因此没有问题。

原文:dev.mysql.com/doc/refman/8.0/en/replication-gtids-functions.html

19.1.3.8 操作 GTID 的存储函数示例

本节提供了使用 MySQL 提供的一些内置函数创建的存储函数示例(请参阅第二十七章,存储对象),这些函数可用于与基于 GTID 的复制一起使用,列在此处:

GTID_SUBSET():显示一个 GTID 集合是否是另一个的子集。
GTID_SUBTRACT():返回一个 GTID 集合中不在另一个中的 GTID。
WAIT_FOR_EXECUTED_GTID_SET(): 等待给定 GTID 集合中的所有事务被执行。

有关刚列出的函数的更多信息,请参阅第 14.18.2 节,“与全局事务标识符(GTID)一起使用的函数”。

请注意,在这些存储函数中,分隔符命令已被用于将 MySQL 语句分隔符更改为竖线,如下所示:

mysql> delimiter |

本节中显示的所有存储函数都将 GTID 集合的字符串表示作为参数,因此在与它们一起使用时,GTID 集合必须始终带引号。

此函数在两个 GTID 集合相同时返回非零(true),即使它们的格式不同:

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

此函数在两个 GTID 集合不相交时返回非零(true):

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

此函数在两个 GTID 集合不相交且sum为它们的并集时返回非零(true):

CREATE FUNCTION GTID_IS_DISJOINT_UNION(gs1 LONGTEXT, gs2 LONGTEXT, sum LONGTEXT)
RETURNS INT
RETURN GTID_IS_EQUAL(GTID_SUBTRACT(sum, gs1), gs2) AND
GTID_IS_EQUAL(GTID_SUBTRACT(sum, gs2), gs1)
|

此函数返回 GTID 集合的规范形式,全部大写,无空格和无重复,UUID 按字母顺序排列,间隔按数字顺序排列:

CREATE FUNCTION GTID_NORMALIZE(gs LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(gs, \’\’)
|

此函数返回两个 GTID 集合的并集:

CREATE FUNCTION GTID_UNION(gs1 LONGTEXT, gs2 LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_NORMALIZE(CONCAT(gs1, \’,\’, gs2))
|

此函数返回两个 GTID 集合的交集。

CREATE FUNCTION GTID_INTERSECTION(gs1 LONGTEXT, gs2 LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(gs1, GTID_SUBTRACT(gs1, gs2))
|

此函数返回两个 GTID 集合之间的对称差异,即存在于gs1中但不存在于gs2中的 GTID,以及存在于gs2中但不存在于gs1中的 GTID。

CREATE FUNCTION GTID_SYMMETRIC_DIFFERENCE(gs1 LONGTEXT, gs2 LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(CONCAT(gs1, \’,\’, gs2), GTID_INTERSECTION(gs1, gs2))
|

此函数从 GTID 集合中删除所有具有指定来源的 GTID,并返回剩余的 GTID(如果有的话)。 UUID 是服务器的标识符,事务通常是在server_uuid中的值。

CREATE FUNCTION GTID_SUBTRACT_UUID(gs LONGTEXT, uuid TEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(gs, CONCAT(UUID, \’:1-\’, (1 << 63) – 2))
|

此函数充当前一个函数的反向;它仅返回来自具有指定标识符(UUID)的服务器的 GTID 集合中的 GTID。

CREATE FUNCTION GTID_INTERSECTION_WITH_UUID(gs LONGTEXT, uuid TEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(gs, GTID_SUBTRACT_UUID(gs, uuid))
|

示例 19.1 验证副本是否最新

内置函数GTID_SUBSET()和GTID_SUBTRACT()可用于检查副本是否至少应用了源应用的每个事务。

要使用GTID_SUBSET()执行此检查,请在副本上执行以下语句:

SELECT GTID_SUBSET(*source_gtid_executed*, *replica_gtid_executed*);

如果返回值为 0(false),则意味着 source_gtid_executed 中的一些 GTID 不在 replica_gtid_executed 中,并且副本尚未应用在源上应用的事务,这意味着副本不是最新的。

要使用 GTID_SUBTRACT() 执行相同的检查,在副本上执行以下语句:

SELECT GTID_SUBTRACT(*source_gtid_executed*, *replica_gtid_executed*);

此语句返回在 source_gtid_executed 中但不在 replica_gtid_executed 中的任何 GTID。如果返回任何 GTID,则表示源已应用了一些副本尚未应用的事务,因此副本不是最新的。

示例 19.2 备份和恢复场景

存储函数 GTID_IS_EQUAL()、GTID_IS_DISJOINT() 和 GTID_IS_DISJOINT_UNION() 可用于验证涉及多个数据库和服务器的备份和恢复操作。在此示例场景中,server1 包含数据库 db1,server2 包含数据库 db2。目标是将数据库 db2 复制到 server1,并且在 server1 上的结果应该是两个数据库的并集。使用的步骤是使用 mysqldump 备份 server2,然后在 server1 上恢复此备份。

运行 mysqldump 时,如果使用了 –set-gtid-purged 参数设置为 ON 或 AUTO(默认值),输出将包含一个 SET @@GLOBAL.gtid_purged 语句,该语句将从 server2 的 gtid_executed 集合添加到 server1 的 gtid_purged 集合中。gtid_purged 包含在给定服务器上已提交但在服务器上任何二进制日志文件中不存在的所有事务的 GTID。当将数据库 db2 复制到 server1 时,必须将在 server2 上提交的事务的 GTID(这些事务不在 server1 的二进制日志文件中)添加到 server1 的 gtid_purged 中,以使集合完整。

存储函数可用于协助此场景中的以下步骤:

使用 GTID_IS_EQUAL() 验证备份操作是否为 SET @@GLOBAL.gtid_purged 语句计算了正确的 GTID 集合。在 server2 上,从 mysqldump 输出中提取该语句,并将 GTID 集合存储到一个本地变量中,例如 $gtid_purged_set。然后执行以下语句:
server2> SELECT GTID_IS_EQUAL($gtid_purged_set, @@GLOBAL.gtid_executed);
如果结果为 1,则两个 GTID 集合相等,且集合已正确计算。
使用GTID_IS_DISJOINT()验证mysqldump输出中的 GTID 集与server1上的gtid_executed集不重叠。在两个服务器上存在相同的 GTID 会导致将数据库db2复制到server1时出现错误。要检查,在server1上,从输出中提取并存储gtid_purged到一个本地变量中,然后执行以下语句:
server1> SELECT GTID_IS_DISJOINT($gtid_purged_set, @@GLOBAL.gtid_executed);
如果结果为 1,则两个 GTID 集之间没有重叠,因此不存在重复的 GTID。
使用GTID_IS_DISJOINT_UNION()验证还原操作是否在server1上导致正确的 GTID 状态。在还原备份之前,在server1上执行以下语句获取现有的gtid_executed集:
server1> SELECT @@GLOBAL.gtid_executed;
将结果存储在本地变量$original_gtid_executed中,以及如前所述,将gtid_purged中的集合存储在另一个本地变量中。当从server2恢复备份到server1时,执行以下语句验证 GTID 状态:
server1> SELECT
-> GTID_IS_DISJOINT_UNION($original_gtid_executed,
-> $gtid_purged_set,
-> @@GLOBAL.gtid_executed);
如果结果为1,则存储的函数已验证来自server1的原始gtid_executed集($original_gtid_executed)和从server2添加的gtid_purged集($gtid_purged_set)没有重叠,并且server1上更新的gtid_executed集现在包括来自server1的先前gtid_executed集以及来自server2的gtid_purged集,这是期望的结果。确保在server1上发生任何进一步的事务之前进行此检查,否则gtid_executed中的新事务将导致其失败。

示例 19.3 选择最新的副本进行手动故障转移

存储函数GTID_UNION()可用于从一组副本中识别最新的副本,以便在源服务器意外停止后执行手动故障转移操作。如果一些副本正在经历复制延迟,此存储函数可用于计算最新的副本,而无需等待所有副本应用其现有的中继日志,从而最小化故障转移时间。该函数可以返回每个副本上的gtid_executed与副本接收到的事务集的并集,该事务集记录在性能模式replication_connection_status表中。您可以比较这些结果,找出哪个副本的事务记录是最新的,即使并非所有事务都已提交。

在每个副本上,通过执行以下语句计算完整的事务记录:

SELECT GTID_UNION(RECEIVED_TRANSACTION_SET, @@GLOBAL.gtid_executed)
FROM performance_schema.replication_connection_status
WHERE channel_name = \’name\’;

然后可以比较每个副本的结果,看哪个副本具有最新的事务记录,并将此副本用作新的源。

示例 19.4 检查副本上的多余交易

存储函数GTID_SUBTRACT_UUID()可用于检查副本是否接收了未来自其指定来源或来源的交易。如果有,则可能存在复制设置问题,或代理、路由器或负载均衡器存在问题。此函数通过从指定起始服务器的 GTID 集合中移除所有 GTID,并返回剩余的 GTID(如果有)来工作。

对于具有单个来源的副本,请发出以下语句,提供起始来源的标识符,通常与server_uuid相同:

SELECT GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed, server_uuid_of_source);

如果结果不为空,则返回的交易是未来自指定来源的额外交易。

对于多源拓扑中的副本,请在函数调用中包含每个来源的服务器 UUID,如下所示:

SELECT
GTID_SUBTRACT_UUID(GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed,
server_uuid_of_source_1),
server_uuid_of_source_2);

如果结果不为空,则返回的交易是未来自任何指定来源的额外交易。

示例 19.5 验证复制拓扑中的服务器是否为只读

存储函数GTID_INTERSECTION_WITH_UUID()可用于验证服务器是否未发起任何 GTID 并处于只读状态。该函数仅返回来自具有指定标识符的服务器的 GTID 集合中的那些 GTID。如果在此服务器的gtid_executed中列出的任何交易使用服务器自己的标识符,则服务器本身发起了这些交易。您可以在服务器上发出以下语句进行检查:

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

示例 19.6 在多源复制中验证额外的副本

存储函数GTID_INTERSECTION_WITH_UUID()可用于查找附加到多源复制设置的副本是否已应用来自一个特定源的所有事务。在这种情况下,source1和source2都是源和副本,并相互复制。source2还有自己的副本。如果source2配置为log_replica_updates=ON,则副本还会接收并应用来自source1的事务,但如果source2使用log_replica_updates=OFF,则不会这样做。无论哪种情况,我们目前只想知道副本是否与source2保持同步。在这种情况下,GTID_INTERSECTION_WITH_UUID()可用于识别source2发起的事务,丢弃source2从source1复制的事务。然后可以使用内置函数GTID_SUBSET()将结果与副本上的gtid_executed集进行比较。如果副本与source2保持同步,则副本上的gtid_executed集包含交集集中的所有事务(源自source2的事务)。

要执行此检查,请将source2的gtid_executed值和服务器 UUID 以及副本中的gtid_executed值存储到用户变量中,如下所示:

source2> SELECT @@GLOBAL.gtid_executed INTO @source2_gtid_executed;
source2> SELECT @@GLOBAL.server_uuid INTO @source2_server_uuid;
replica> SELECT @@GLOBAL.gtid_executed INTO @replica_gtid_executed;

然后使用GTID_INTERSECTION_WITH_UUID()和GTID_SUBSET(),并将这些变量作为输入,如下所示:

SELECT
GTID_SUBSET(
GTID_INTERSECTION_WITH_UUID(@source2_gtid_executed,
@source2_server_uuid),
@replica_gtid_executed);

来自source2的服务器标识符(@source2_server_uuid)与GTID_INTERSECTION_WITH_UUID()一起使用,仅识别并返回那些在source2上发起的 GTID,省略那些在source1上发起的。然后,使用GTID_SUBSET()将生成的 GTID 集与副本上的所有已执行 GTID 集进行比较。如果此语句返回非零(true),则从source2识别的所有 GTID(第一个输入集)也在副本的gtid_executed中找到,这意味着副本已接收并执行了所有源自source2的事务。
负载均衡器存在问题。此函数通过从指定起始服务器的 GTID 集合中移除所有 GTID,并返回剩余的 GTID(如果有)来工作。

对于具有单个来源的副本,请发出以下语句,提供起始来源的标识符,通常与server_uuid相同:

SELECT GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed, server_uuid_of_source);

如果结果不为空,则返回的交易是未来自指定来源的额外交易。

对于多源拓扑中的副本,请在函数调用中包含每个来源的服务器 UUID,如下所示:

SELECT
GTID_SUBTRACT_UUID(GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed,
server_uuid_of_source_1),
server_uuid_of_source_2);

如果结果不为空,则返回的交易是未来自任何指定来源的额外交易。

示例 19.5 验证复制拓扑中的服务器是否为只读

存储函数GTID_INTERSECTION_WITH_UUID()可用于验证服务器是否未发起任何 GTID 并处于只读状态。该函数仅返回来自具有指定标识符的服务器的 GTID 集合中的那些 GTID。如果在此服务器的gtid_executed中列出的任何交易使用服务器自己的标识符,则服务器本身发起了这些交易。您可以在服务器上发出以下语句进行检查:

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

示例 19.6 在多源复制中验证额外的副本

存储函数GTID_INTERSECTION_WITH_UUID()可用于查找附加到多源复制设置的副本是否已应用来自一个特定源的所有事务。在这种情况下,source1和source2都是源和副本,并相互复制。source2还有自己的副本。如果source2配置为log_replica_updates=ON,则副本还会接收并应用来自source1的事务,但如果source2使用log_replica_updates=OFF,则不会这样做。无论哪种情况,我们目前只想知道副本是否与source2保持同步。在这种情况下,GTID_INTERSECTION_WITH_UUID()可用于识别source2发起的事务,丢弃source2从source1复制的事务。然后可以使用内置函数GTID_SUBSET()将结果与副本上的gtid_executed集进行比较。如果副本与source2保持同步,则副本上的gtid_executed集包含交集集中的所有事务(源自source2的事务)。

要执行此检查,请将source2的gtid_executed值和服务器 UUID 以及副本中的gtid_executed值存储到用户变量中,如下所示:

source2> SELECT @@GLOBAL.gtid_executed INTO @source2_gtid_executed;
source2> SELECT @@GLOBAL.server_uuid INTO @source2_server_uuid;
replica> SELECT @@GLOBAL.gtid_executed INTO @replica_gtid_executed;

然后使用GTID_INTERSECTION_WITH_UUID()和GTID_SUBSET(),并将这些变量作为输入,如下所示:

SELECT
GTID_SUBSET(
GTID_INTERSECTION_WITH_UUID(@source2_gtid_executed,
@source2_server_uuid),
@replica_gtid_executed);

来自source2的服务器标识符(@source2_server_uuid)与GTID_INTERSECTION_WITH_UUID()一起使用,仅识别并返回那些在source2上发起的 GTID,省略那些在source1上发起的。然后,使用GTID_SUBSET()将生成的 GTID 集与副本上的所有已执行 GTID 集进行比较。如果此语句返回非零(true),则从source2识别的所有 GTID(第一个输入集)也在副本的gtid_executed中找到,这意味着副本已接收并执行了所有源自source2的事务。

#以上关于MySQL8 中文参考(七十六)的相关内容来源网络仅供参考,相关信息请以官方公告为准!

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92451.html

Like (0)
CSDN的头像CSDN
Previous 2024年6月27日
Next 2024年6月27日

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注