#### 17.1.5.2 为基于 GTID 的复制提供多源副本

[](<>)

如果多源复制拓扑中的源具有现有数据，则可以在开始复制之前为副本提供相关数据，从而节省时间。在多源复制拓扑中，无法使用数据目录的克隆或复制来为副本提供来自所有源的数据，并且您可能还希望仅复制来自每个源的特定数据库。因此，提供此类副本的最佳策略是使用[**mysql转储**](mysqldump.html)在每个源上创建适当的转储文件，然后使用[**mysql**](mysql.html)客户端导入副本上的转储文件。

如果您使用基于 GTID 的复制，则需要注意`SET @@GLOBAL.gtid_purged`声明[**mysql转储**](mysqldump.html)放置在转储输出中。此语句将源上执行的事务的 GTID 传输到副本，副本需要此信息。但是，对于任何比从一个源配置一个新的空副本更复杂的情况，您需要检查该语句对副本使用的 MySQL 版本的影响，并相应地处理该语句。以下指南总结了合适的操作，但有关更多详细信息，请参阅[**mysql转储**](mysqldump.html)文档。

的行为`SET @@GLOBAL.gtid_purged`写的声明[**mysql转储**](mysqldump.html)与 MySQL 5.6 和 5.7 相比，MySQL 8.0 的版本不同。在 MySQL 5.6 和 5.7 中，语句替换了[`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged)在副本上，以及在那些版本中，只有当副本的带有 GTID 的事务记录（[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)集）为空。因此，在多源复制拓扑中，您​​必须删除`SET @@GLOBAL.gtid_purged`在重播转储文件之前从转储输出中提取语句，因为您无法应用包含此语句的第二个或后续转储文件。另请注意，对于 MySQL 5.6 和 5.7，此限制意味着来自源的所有转储文件必须在单个操作中应用于具有空副本的副本[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)放。您可以通过发出清除副本的 GTID 执行历史记录[`复位主机`](reset-master.html)在副本上，但如果您在副本上有其他需要 GTID 的事务，请从中描述的方法中选择一种替代方法[第 17.1.3.5 节，“使用 GTID 进行故障转移和横向扩展”](replication-gtids-failover.html).

从 MySQL 8.0 开始，`SET @@GLOBAL.gtid_purged`语句将转储文件中的 GTID 集添加到现有的[`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged)在副本上设置。因此，当您在副本上重放转储文件时，该语句可能会留在转储输出中，并且可以在不同时间重放转储文件。但是，重要的是要注意包含的值[**mysql转储**](mysqldump.html)为了`SET @@GLOBAL.gtid_purged`语句包括所有事务的 GTID[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)在源上设置，即使那些更改了数据库的隐藏部分，或服务器上未包含在部分转储中的其他数据库。如果您在包含任何相同 GTID 的副本上重放第二个或后续转储文件（例如，来自同一源的另一个部分转储，或来自具有重叠事务的另一个源的转储），则任何`SET @@GLOBAL.gtid_purged`第二个转储文件中的语句失败，因此必须从转储输出中删除。

对于来自 MySQL 8.0.17 的源，作为删除`SET @@GLOBAL.gtid_purged`声明，你可以设置[**mysql转储**](mysqldump.html)的`--set-gtid-purge`选项`已评论`包含该语句但已注释掉，以便在您加载转储文件时不会执行此操作。如果您使用来自同一源的两个部分转储来配置副本，并且在第二个转储中设置的 GTID 与第一个相同（因此在转储之间的源上没有执行任何新事务），您可以设置[**mysql转储**](mysqldump.html)的`--set-gtid-purge`选项`离开`当您输出第二个转储文件时，省略该语句。

在以下配置示例中，我们假设`SET @@GLOBAL.gtid_purged`语句不能留在转储输出中，必须从文件中删除并手动处理。我们还假设在配置开始之前副本上没有带有 GTID 的所需事务。

1.  为名为的数据库创建转储文件`db1`在`来源1`和一个名为`数据库2`在`来源2`， 跑步[**mysql转储**](mysqldump.html)为了`来源1`如下：

    ```
    mysqldump -u<user> -p<password> --single-transaction --triggers --routines --set-gtid-purged=ON --databases db1 > dumpM1.sql
    ```

    然后运行[**mysql转储**](mysqldump.html)为了`来源2`详情如下：

    ```
    mysqldump -u<user> -p<password> --single-transaction --triggers --routines --set-gtid-purged=ON --databases db2 > dumpM2.sql
    ```

2.  记录[`gtid_`](replication-options-gtids.html#sysvar_gtid_purged)重视这一点[**mysqldump**](mysqldump.html)添加到每个转储文件。例如，对于在MySQL 5.6或5.7上创建的转储文件，可以这样提取值：

    ```
    cat dumpM1.sql | grep GTID_PURGED | cut -f2 -d'=' | cut -f2 -d$'\''
    cat dumpM2.sql | grep GTID_PURGED | cut -f2 -d'=' | cut -f2 -d$'\''
    ```

    从格式已更改的MySQL 8.0中，可以提取如下值：

    ```
    cat dumpM1.sql | grep GTID_PURGED | perl -p0 -e 's#/\*.*?\*/##sg' | cut -f2 -d'=' | cut -f2 -d$'\''
    cat dumpM2.sql | grep GTID_PURGED | perl -p0 -e 's#/\*.*?\*/##sg' | cut -f2 -d'=' | cut -f2 -d$'\''
    ```

    每种情况下的结果都应该是GTID集，例如：

    ```
    source1:   2174B383-5441-11E8-B90A-C80AA9429562:1-1029
    source2:   224DA167-0C0C-11E8-8442-00059A3C7B00:1-2695
    ```

3.  从每个包含`设置@@GLOBAL。gtid_`陈述例如：

    ```
    sed '/GTID_PURGED/d' dumpM1.sql > dumpM1_nopurge.sql
    sed '/GTID_PURGED/d' dumpM2.sql > dumpM2_nopurge.sql
    ```

4.  使用[**mysql**](mysql.html)客户端将每个编辑的转储文件导入副本。例如：

    ```
    mysql -u<user> -p<password> < dumpM1_nopurge.sql
    mysql -u<user> -p<password> < dumpM2_nopurge.sql
    ```

5.  关于复制品问题[`重置主机`](reset-master.html)清除GTID执行历史记录（如上所述，假设所有转储文件都已导入，并且副本上没有需要的GTID事务）。然后发布`设置@@GLOBAL。gtid_`语句来设置[`gtid_`](replication-options-gtids.html#sysvar_gtid_purged)值为所有转储文件中所有GTID集的并集，如您在步骤2中记录的。例如：

    ```
    mysql> RESET MASTER;
    mysql> SET @@GLOBAL.gtid_purged = "2174B383-5441-11E8-B90A-C80AA9429562:1-1029, 224DA167-0C0C-11E8-8442-00059A3C7B00:1-2695";
    ```

    如果转储文件中的GTID集之间存在或可能存在重叠事务，则可以使用中描述的存储函数[第17.1.3.8节，“操作GTID的存储函数示例”](replication-gtids-functions.html)提前检查并计算所有GTID集合的并集。
