### 23.7.10 NDB 集群复制：双向和循环复制

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

可以使用 NDB Cluster 在两个集群之间进行双向复制，也可以在任意数量的集群之间进行循环复制。

**循环复制示例。**在接下来的几段中，我们考虑一个复制设置的示例，该示例涉及三个 NDB Cluster，编号为 1、2 和 3，其中 Cluster 1 作为 Cluster 2 的复制源，Cluster 2 作为 Cluster 3 的源，Cluster3 作为集群 1 的源。每个集群有两个 SQL 节点，SQL 节点 A 和 B 属于集群 1，SQL 节点 C 和 D 属于集群 2，SQL 节点 E 和 F 属于集群 3。

只要满足以下条件，就支持使用这些集群的循环复制：

-   所有源和副本上的 SQL 节点都是相同的。

-   所有充当源和副本的 SQL 节点都使用系统变量启动[`log_replica_updates`](replication-options-binary-log.html#sysvar_log_replica_updates)（来自 MySQL 8.0.26）或[`log_slave_updates`](replication-options-binary-log.html#sysvar_log_slave_updates)（在 MySQL 8.0.26 之前）已启用。

    这种类型的循环复制设置如下图所示：

[](<>)

**图 23.36 所有源都作为副本的 NDB Cluster 循环复制**

<img alt="Some content is described in the surrounding text. The diagram shows three clusters, each with two nodes. Arrows connecting SQL nodes in different clusters illustrate that all sources are also replicas." src="images/cluster-circular-replication-1.png" height="883" width="557" />

在这种情况下，集群 1 中的 SQL 节点 A 复制到集群 2 中的 SQL 节点 C；SQL 节点 C 复制到集群 3 中的 SQL 节点 E；SQL 节点 E 复制到 SQL 节点 A。也就是说，复制线（由图中的弯曲箭头表示）直接连接所有用作复制源和副本的 SQL 节点。也可以设置循环复制，使并非所有源 SQL 节点也是副本，如下所示：

图 23.37 并非所有源都是副本的 NDB Cluster 循环复制

[](<>)

**在这种情况下，每个集群中的不同 SQL 节点被用作复制源和副本。**

<img alt="Some content is described in the surrounding text. The diagram shows three clusters, each with two nodes. Arrows connecting SQL nodes in different clusters illustrate that not all sources are replicas." src="images/cluster-circular-replication-2.png" height="877" width="542" />

你必须不是*使用系统变量启动任何 SQL 节点*log_replica_updates[`（来自 MySQL 8.0.26）或`](replication-options-binary-log.html#sysvar_log_replica_updates)log_slave_updates[`（在 MySQL 8.0.26 之前）已启用。`](replication-options-binary-log.html#sysvar_log_slave_updates)这种类型的 NDB Cluster 循环复制方案，其中复制线（再次由图中的弯曲箭头指示）是不连续的，应该是可能的，但应该注意它尚未经过彻底测试，因此必须仍然被认为是实验性的。

**使用 NDB-native 备份和还原来初始化副本集群。**  [](<>)设置循环复制时，可以使用管理客户端初始化副本集群[`开始备份`](mysql-cluster-backup-using-management-client.html)命令在一个 NDB Cluster 上创建备份，然后使用此备份在另一个 NDB Cluster 上应用[**数据库\_恢复**](mysql-cluster-programs-ndb-restore.html)。这不会自动在作为副本的第二个NDB群集的SQL节点上创建二进制日志；为了创建二进制日志，必须发出[`展示桌子`](show-tables.html)SQL节点上的语句；这应该在运行之前完成[`开始复制`](start-replica.html).这是一个已知的问题。

**多源故障切换示例。**在本节中，我们将讨论多源NDB群集复制设置中的故障切换，该设置包含三个服务器ID为1、2和3的NDB群集。在这个场景中，集群1复制到集群2和集群3；集群2也复制到集群3。这种关系如下所示：

[](<>)

**图23.38具有3个源的NDB群集多主机复制**

<img alt="Multi-source NDB Cluster replication setup with three NDB Clusters having server IDs 1, 2, and 3; Cluster 1 replicates to Clusters 2 and 3; Cluster 2 also replicates to Cluster 3." src="images/cluster-replication-multi-source.png" height="235" width="366" />

换句话说，数据通过两种不同的路径从集群1复制到集群3：直接复制和通过集群2复制。

并非所有参与多源复制的MySQL服务器都必须同时充当源和副本，而且给定的NDB集群可能会为不同的复制通道使用不同的SQL节点。这种情况如下所示：

[](<>)

**图23.39使用MySQL服务器的NDB群集多源复制**

<img alt="Concepts are described in the surrounding text. Shows three nodes: SQL node A in Cluster 1 replicates to SQL node F in Cluster 3; SQL node B in Cluster 1 replicates to SQL node C in Cluster 2; SQL node E in Cluster 3 replicates to SQL node G in Cluster 3. SQL nodes A and B in cluster 1 have --log-slave-updates=0; SQL nodes C in Cluster 2, and SQL nodes F and G in Cluster 3 have --log-slave-updates=1; and SQL nodes D and E in Cluster 2 have --log-slave-updates=0." src="images/cluster-replication-multi-source-mysqlds.png" height="596" width="692" />

作为副本的MySQL服务器必须使用系统变量运行[`日志副本更新`](replication-options-binary-log.html#sysvar_log_replica_updates)（来自MySQL 8.0.26）或[`日志_slave _更新`](replication-options-binary-log.html#sysvar_log_slave_updates)（MySQL 8.0.26之前）已启用。哪一个[**mysqld**](mysqld.html)流程需要此选项，如上图所示。

笔记

使用[`日志副本更新`](replication-options-binary-log.html#sysvar_log_replica_updates)或[`日志_slave _更新`](replication-options-binary-log.html#sysvar_log_slave_updates)系统变量对不作为副本运行的服务器没有影响。

当其中一个复制群集发生故障时，就需要进行故障切换。在这个例子中，我们考虑集群1丢失到服务的情况，因此集群3从群集1丢失了2个更新源。因为NDB集群之间的复制是异步的，所以不能保证直接从集群1发出的集群3的更新比通过集群2收到的更新更新。您可以通过确保集群3在集群1的更新方面赶上集群2来处理这个问题。就MySQL服务器而言，这意味着您需要将任何未完成的更新从MySQL服务器C复制到服务器F。

在服务器C上，执行以下查询：

```
mysqlC> SELECT @latest:=MAX(epoch)
     ->     FROM mysql.ndb_apply_status
     ->     WHERE server_id=1;

mysqlC> SELECT
     ->     @file:=SUBSTRING_INDEX(File, '/', -1),
     ->     @pos:=Position
     ->     FROM mysql.ndb_binlog_index
     ->     WHERE orig_epoch >= @latest
     ->     AND orig_server_id = 1
     ->     ORDER BY epoch ASC LIMIT 1;
```

笔记

通过向查询中添加适当的索引，可以提高此查询的性能，从而可能显著加快故障切换时间`ndb_binlog_索引`桌子看见[第23.7.4节，“NDB群集复制模式和表”](mysql-cluster-replication-schema.html)，以获取更多信息。

复制以下值：*`@文件`*和*`@位置`*手动从服务器C到服务器F（或让您的应用程序执行等效操作）。然后，在服务器F上执行以下操作[`将复制源更改为`](change-replication-source-to.html)语句（MySQL 8.0.23及更高版本）或[`将主机更改为`](change-master-to.html)声明（MySQL 8.0.23之前）：

```
mysqlF> CHANGE MASTER TO
     ->     MASTER_HOST = 'serverC'
     ->     MASTER_LOG_FILE='@file',
     ->     MASTER_LOG_POS=@pos;
```

从MySQL 8.0.23开始，您还可以使用以下语句：

```
mysqlF> CHANGE REPLICATION SOURCE TO
     ->     SOURCE_HOST = 'serverC'
     ->     SOURCE_LOG_FILE='@file',
     ->     SOURCE_LOG_POS=@pos;
```

完成后，您可以发布[`开始复制`](start-replica.html)MySQL服务器F上的语句；这会导致将源于服务器B的任何缺失更新复制到服务器F。

这个[`将复制源更改为`](change-replication-source-to.html) \| [`将主机更改为`](change-master-to.html)语句还支持`忽略服务器ID`选项，该选项采用以逗号分隔的服务器ID列表，并导致忽略源自相应服务器的事件。有关更多信息，请参阅[第13.4.2.1节，“将主报表更改为报表”](change-master-to.html)和[第13.7.7.36节，“显示从机|副本状态声明”](show-slave-status.html)。有关此选项与[`ndb_日志_应用_状态`](mysql-cluster-options-variables.html#sysvar_ndb_log_apply_status)变量，参见[第23.7.8节，“使用NDB群集复制实现故障切换”](mysql-cluster-replication-failover.html).
