#### 17.1.3.5 使用 GTID 进行故障转移和横向扩展

[](<>)[](<>)

使用带有全局事务标识符 (GTID) 的 MySQL 复制来提供新的副本时，有许多技术可以用于横向扩展，并在必要时提升为源以进行故障转移。本节介绍以下技术：

-   [简单复制](replication-gtids-failover.html#replication-gtids-failover-replicate)

-   [将数据和事务复制到副本](replication-gtids-failover.html#replication-gtids-failover-copy)

-   [注入空事务](replication-gtids-failover.html#replication-gtids-failover-empty)

-   [排除带有 gtid 的事务\_清除](replication-gtids-failover.html#replication-gtids-failover-gtid-purged)

-   [恢复 GTID 模式副本](replication-gtids-failover.html#replication-gtids-restoring-mysqlbinlog)

    为了简化复制数据流的一般管理，特别是故障转移活动，将全局事务标识符添加到 MySQL 复制中。每个标识符唯一标识一组二进制日志事件，这些事件共同构成一个事务。GTID 在将更改应用到数据库中起着关键作用：服务器自动跳过任何具有服务器识别为它之前处理过的标识符的标识符的事务。此行为对于自动复制定位和正确的故障转移至关重要。

    标识符和组成给定事务的事件集之间的映射被捕获在二进制日志中。在为新服务器配置来自另一台现有服务器的数据时，这会带来一些挑战。为了在新服务器上重现标识符集，需要将标识符从旧服务器复制到新服务器，并保留标识符与实际事件之间的关系。这对于还原可立即用作候选以在故障转移或切换时成为新源的副本是必要的。

[](<>)**简单的复制。**在新服务器上重现所有标识符和事务的最简单方法是使新服务器成为具有完整执行历史的源的副本，并在两台服务器上启用全局事务标识符。看[第 17.1.3.4 节，“使用 GTID 设置复制”](replication-gtids-howto.html)， 了解更多信息。

复制开始后，新服务器会从源复制整个二进制日志，从而获取有关所有 GTID 的所有信息。

这种方法简单有效，但需要副本从源读取二进制日志；有时新副本赶上源需要比较长的时间，因此这种方法不适合快速故障转移或从备份恢复。本节说明如何通过将二进制日志文件复制到新服务器来避免从源获取所有执行历史记录。

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

此方法有多种变体，不同之处在于将二进制日志中的数据转储和事务传输到副本的方式，如下所述：

数据集

1.  使用创建转储文件[**mysql转储**](mysqldump.html)在源服务器上。设置[**mysql转储**](mysqldump.html)选项[`- 主要的数据`](mysqldump.html#option_mysqldump_master-data)（默认值为 1）包括一个[`将复制源更改为`](change-replication-source-to.html)\|[`将主更改为`](change-master-to.html)带有二进制日志信息的语句。设置[`--set-gtid-purge`](mysqldump.html#option_mysqldump_set-gtid-purged)选项`汽车`（默认）或`在`，以在转储中包含有关已执行事务的信息。然后使用[**mysql**](mysql.html)客户端导入目标服务器上的转储文件。

2.  或者，使用原始数据文件创建源服务器的数据快照，然后按照中的说明将这些文件复制到目标服务器[第 17.1.2.5 节，“选择数据快照的方法”](replication-snapshot-method.html).如果你使用[`InnoDB`](innodb-storage-engine.html)表，您可以使用**mysql备份**来自 MySQL Enterprise Backup 组件的命令以生成一致的快照。此命令记录要在副本上使用的快照对应的日志名称和偏移量。MySQL Enterprise Backup 是一种商业产品，包含在 MySQL Enterprise 订阅中。看[第 30.2 节，“MySQL 企业备份概述”](mysql-enterprise-backup.html)了解详细信息。

3.  或者，停止源服务器和目标服务器，将源数据目录的内容复制到新副本的数据目录，然后重新启动副本。如果使用此方法，则必须将副本配置为基于 GTID 的复制，换句话说[`gtid_mode=ON`](replication-options-gtids.html#sysvar_gtid_mode).有关此方法的说明和重要信息，请参阅[第 17.1.2.8 节，“将副本添加到复制环境”](replication-howto-additionalslaves.html).

    交易记录

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

4.  使用以下命令将二进制日志从源服务器导入到新副本[**mysqlbinlog**](mysqlbinlog.html), 与[`--从远程服务器读取`](mysqlbinlog.html#option_mysqlbinlog_read-from-remote-server),[`--从远程源读取`](mysqlbinlog.html#option_mysqlbinlog_read-from-remote-source)， 和[`--从远程主机读取`](mysqlbinlog.html#option_mysqlbinlog_read-from-remote-master)选项。

5.  或者，将源服务器的二进制日志文件复制到副本。您可以使用从副本制作副本[**mysqlbinlog**](mysqlbinlog.html)与[`--从远程服务器读取`](mysqlbinlog.html#option_mysqlbinlog_read-from-remote-server)和[`- 生的`](mysqlbinlog.html#option_mysqlbinlog_raw)选项。这些可以通过使用读入副本[**mysqlbinlog**](mysqlbinlog.html) `>` `*`文件`*`（没有[`- 生的`](mysqlbinlog.html#option_mysqlbinlog_raw)选项）将二进制日志文件导出到 SQL 文件，然后将这些文件传递给[**mysql**](mysql.html)客户端进行处理。确保使用单个处理所有二进制日志文件[**mysql**](mysql.html)进程，而不是多个连接。例如：

    ```
    $> mysqlbinlog copied-binlog.000001 copied-binlog.000002 | mysql -u root -p
    ```

    有关详细信息，请参阅[第 4.6.9.3 节，“使用 mysqlbinlog 备份二进制日志文件”](mysqlbinlog-backup.html).

    这种方法的优点是几乎可以立即使用新服务器；只有在重放快照或转储文件时提交的那些事务仍需要从现有源中获取。这意味着副本的可用性不是即时的，但副本只需要相对较短的时间即可赶上这几个剩余事务。

    提前将二进制日志复制到目标服务器通常比从源实时读取整个事务执行历史记录要快。但是，由于大小或其他考虑，在需要时将这些文件移动到目标可能并不总是可行的。本节中讨论的用于供应新副本的其余两种方法使用其他方式将有关事务的信息传输到新副本。

[](<>)**注入空事务。**源的全球[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)变量包含在源上执行的所有事务的集合。无需在拍摄快照以配置新服务器时复制二进制日志，您可以改为记下`gtid_executed`在从中拍摄快照的服务器上。在将新服务器添加到复制链之前，只需在新服务器上为源的每个事务标识符提交一个空事务`gtid_executed`， 像这样：

```
SET GTID_NEXT='aaa-bbb-ccc-ddd:N';

BEGIN;
COMMIT;

SET GTID_NEXT='AUTOMATIC';
```

一旦使用空事务以这种方式恢复了所有事务标识符，您必须刷新并清除副本的二进制日志，如此处所示，其中*`ñ`*是当前二进制日志文件名的非零后缀：

```
FLUSH LOGS;
PURGE BINARY LOGS TO 'source-bin.00000N';
```

您应该这样做，以防止此服务器在稍后将其提升为源时使用虚假事务淹没复制流。（这[`刷新日志`](flush.html#flush-logs)语句强制创建一个新的二进制日志文件；[`清除二进制日志`](purge-binary-logs.html)清除空事务，但保留其标识符。）

这种方法创建的服务器本质上是一个快照，但随着它的二进制日志历史与复制流的历史收敛（即，它赶上一个或多个源），它能够及时成为一个源。这个结果与使用剩余供应方法获得的结果相似，我们将在接下来的几段中讨论。

[](<>)**排除带有 gtid 的事务\_清除。**源的全球[`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged)变量包含已从源的二进制日志中清除的所有事务的集合。与前面讨论的方法一样（参见[注入空事务](replication-gtids-failover.html#replication-gtids-failover-empty))，您可以记录的值[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)在从中获取快照的服务器上（代替将二进制日志复制到新服务器）。与以前的方法不同，不需要提交空事务（或发出[`清除二进制日志`](purge-binary-logs.html));相反，您可以设置[`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged)直接在副本上，基于值[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)在从中获取备份或快照的服务器上。

与使用空事务的方法一样，此方法创建的服务器在功能上是一个快照，但随着其二进制日志历史与源和其他副本的历史融合，它能够及时成为源。

[](<>)**恢复 GTID 模式副本。**在基于 GTID 的复制设置中恢复遇到错误的副本时，注入空事务可能无法解决问题，因为事件没有 GTID。

采用[**mysqlbinlog**](mysqlbinlog.html)查找下一个事务，这可能是事件后下一个日志文件中的第一个事务。将所有内容复制到`犯罪`对于该交易，一定要包括`SET @@SESSION.gtid_next`.即使您不使用基于行的复制，您仍然可以在命令行客户端中运行二进制日志行事件。

停止副本并运行您复制的事务。这[**mysqlbinlog**](mysqlbinlog.html)输出将分隔符设置为`/*!*/;`，所以将其重新设置：

```
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;
```
