

# 为 Amazon Aurora MySQL 配置多源复制
<a name="AuroraMySQL.Replication.MultiSource"></a>

通过多源复制，您可以将 Amazon Aurora MySQL 数据库集群设置为一个副本，该副本接收来自多个源 MySQL 数据库的二进制日志事件。每个源都可以是 RDS for MySQL 数据库实例、另一个 Aurora MySQL 数据库集群，或在 Amazon RDS 外部运行的 MySQL 数据库。

运行以下引擎版本的 Aurora MySQL 数据库集群支持多源复制：
+ Aurora MySQL 8.4.8 及更高版本

有关 MySQL 多源复制的更多信息，请参阅 MySQL 文档中的 [MySQL Multi-Source Replication](https://dev.mysql.com/doc/refman/8.4/en/replication-multi-source.html)。

**注意**  
Aurora MySQL 上的多源复制使用 Aurora 数据库集群的写入器（主）实例作为复制目标。所有复制存储过程都必须在连接到集群的写入器实例时进行调用。

## 多源复制的使用案例
<a name="AuroraMySQL.Replication.MultiSource.UseCases"></a>

在以下情况下，考虑在 Aurora MySQL 上使用多源复制：
+ **分片整合**：需要将托管在各个单独数据库实例上的多个分片中的数据，合并或整合到单个 Aurora MySQL 数据库集群中的应用程序。
+ **整合报告**：需要根据从多个源整合的数据生成报告的应用程序，可充分利用 Aurora 的读取扩展功能。
+ **长期备份**：要求为分布在多个 MySQL 兼容数据库实例中的数据创建整合的长期备份。
+ **跨引擎迁移**：在迁移期间，将来自多个 RDS for MySQL 实例或外部 MySQL 服务器的数据整合到单个 Aurora MySQL 集群中。
+ **多租户聚合**：将多个单租户数据库整合到一个多租户 Aurora 集群中，以优化成本并简化管理。

## 多源复制的先决条件
<a name="AuroraMySQL.Replication.MultiSource.Prerequisites"></a>

在 Aurora MySQL 数据库集群上配置多源复制之前，请完成[为 Aurora MySQL 设置二进制日志复制](AuroraMySQL.Replication.MySQL.SettingUp.md)中所述的二进制日志复制的标准先决条件。这包括在每个源上启用二进制日志记录、保留二进制日志、创建复制用户以及创建每个源的副本或转储。对于多源复制，对每个源数据库实例重复这些步骤。

除标准先决条件外，还需确保满足以下特定于多源复制的要求。
+ 验证 Aurora MySQL 目标集群版本和配置
  + Aurora MySQL 数据库集群必须运行支持的引擎版本（Aurora MySQL 8.4.8 及更高版本）。
  + 在 Aurora MySQL 写入器实例上启用自动提交。在数据库集群参数组中将 `autocommit` 参数设置为 `1`。
+ 为每个源配置网络连接

  对于每个源数据库实例，请确保 Aurora MySQL 写入器实例可以通过指定的端口连接到源。选项包括：
  + 如果源和目标都在同一 VPC 中，请在源数据库实例上配置安全组，以支持从 Aurora MySQL 集群的安全组通过端口 3306（或您的自定义端口）进行入站连接。
  + 如果它们位于不同的 VPC 中，请设置 VPC 对等连接或使用中转网关。有关更多信息，请参阅 [VPC 中的数据库集群由另一 VPC 中的 EC2 实例访问](USER_VPC.Scenarios.md#USER_VPC.Scenario3)。
  + 如果源位于 AWS 外部，请确保网络路由可用（例如，通过 VPN 连接）。

**注意**  
由于多源复制涉及多个源，因此必须单独验证与每个源的连接。确保安全组和路由同时容纳所有源端点。

## 在 Aurora MySQL 数据库集群上配置多源复制通道
<a name="AuroraMySQL.Replication.MultiSource.Configure"></a>

在 Aurora MySQL 上配置多源复制通道与配置单源复制类似。对于多源复制，首先要在源实例上启用二进制日志记录，将数据从源导入到 Aurora MySQL 集群，然后使用二进制日志坐标或 GTID 自动定位功能从每个源开始复制。

**重要**  
连接到 Aurora MySQL 数据库集群的**写入器实例**时，必须调用所有多源复制存储过程。如果发生失效转移，您必须重新连接到新的写入器实例。

### 步骤 1：将数据从源数据库实例导入到 Aurora MySQL 集群
<a name="AuroraMySQL.Replication.MultiSource.Configure.Step1"></a>

对每个源数据库实例执行以下步骤。

1. 确定源数据库实例上的当前二进制日志文件和位置。

   ```
   SHOW BINARY LOG STATUS;
   ```

   ```
   SHOW MASTER STATUS;
   ```

   输出示例：

   ```
   +----------------------------+----------+
   | File                       | Position |
   +----------------------------+----------+
   | mysql-bin-changelog.000031 |      107 |
   +----------------------------+----------+
   ```

   记录 `File` 和 `Position` 值。您在后面的步骤中会用到它们。

1. 使用 `mysqldump` 将数据库从源数据库实例复制到 Aurora MySQL 集群。

   ```
   mysqldump --databases {{database_name}} \
     --single-transaction \
     --compress \
     --order-by-primary \
     -u {{RDS_user_name}} \
     -p'{{RDS_password}}' \
     --host={{source-endpoint.region.rds.amazonaws.com}} | mysql \
     --host={{aurora-cluster-endpoint.cluster-xxxxxx.region.rds.amazonaws.com}} \
     --port=3306 \
     -u {{aurora_user_name}} \
     -p'{{aurora_password}}'
   ```
**提示**  
对于大型数据库，考虑使用 AWS DMS 或创建快照并进行还原，以减少数据传输时间。

1. 数据导入完成后，如果您之前已将源数据库实例设置为只读，则可以重新启用对源数据库实例的写入。

### 步骤 2：开始从源数据库实例复制到 Aurora MySQL 集群
<a name="AuroraMySQL.Replication.MultiSource.Configure.Step2"></a>

对于每个源数据库实例，连接到 Aurora MySQL 数据库集群的**写入器实例**，然后运行存储过程以便在通道上配置和开始复制。

```
CALL mysql.rds_set_external_source_for_channel(
  '{{source-endpoint.region.rds.amazonaws.com}}',
  3306,
  '{{repl_user}}',
  '{{password}}',
  '{{mysql-bin-changelog.000031}}',
  107,
  0,
  '{{channel_1}}'
);

CALL mysql.rds_start_replication_for_channel('{{channel_1}}');
```

如果源数据库实例使用基于 GTID 的复制，则可以使用自动定位，而不是指定二进制日志坐标：

```
CALL mysql.rds_set_external_source_with_auto_position_for_channel(
  '{{source-endpoint.region.rds.amazonaws.com}}',
  3306,
  '{{repl_user}}',
  '{{password}}',
  0,
  0,
  '{{channel_1}}'
);

CALL mysql.rds_start_replication_for_channel('{{channel_1}}');
```

**注意**  
使用 GTID 自动定位时，请确保在所有源实例和 Aurora MySQL 集群中一致地配置 `gtid_mode` 和 `enforce_gtid_consistency` 参数。

对每个源数据库实例重复这些步骤，并为每个源数据库实例指定一个唯一的通道名称（例如 `channel_1`、`channel_2`、`channel_3`）。

## 将筛选条件与多源复制结合使用
<a name="AuroraMySQL.Replication.MultiSource.Filters"></a>

您可以使用复制筛选条件来指定将哪些数据库和表复制到 Aurora MySQL 多源副本。有关复制筛选条件的更多信息，请参阅[使用 Aurora MySQL 配置复制筛选条件](AuroraMySQL.Replication.Filters.md)。下文介绍了多源复制中可用的其它通道级筛选功能。

使用多源复制，您可以在两个级别配置复制筛选条件：
+ **全局筛选条件**：适用于所有通道。使用 Aurora MySQL 数据库集群参数组进行设置（例如 `replicate-do-db`、`replicate-ignore-db`）。
+ **通道级筛选条件**：仅适用于特定通道，并覆盖该通道的全局筛选条件。
+ 更改通道级筛选条件后，必须重新启动复制。
+ 如果未配置特定于通道的筛选条件，Aurora MySQL 会为该通道应用全局筛选条件。
+ 如果在全局和通道级均应用筛选条件，则仅对该通道应用通道级筛选条件。

## 监控多源复制通道
<a name="AuroraMySQL.Replication.MultiSource.Monitoring"></a>

您可以使用以下方法监控 Aurora MySQL 多源副本上的各个通道。

### 使用 SHOW REPLICA STATUS
<a name="AuroraMySQL.Replication.MultiSource.Monitoring.ShowReplicaStatus"></a>

连接到 Aurora MySQL 数据库集群的写入器实例并运行：

```
-- View status for all channels
SHOW REPLICA STATUS\G

-- View status for a specific channel
SHOW REPLICA STATUS FOR CHANNEL '{{channel_1}}'\G
```

要监控的关键字段：


| 字段 | 说明 | 
| --- | --- | 
| Replica\_IO\_Running | 通道的 I/O 线程是否正在运行 | 
| Replica\_SQL\_Running | 通道的 SQL 线程是否正在运行 | 
| Seconds\_Behind\_Source | 通道的复制滞后（以秒为单位） | 
| Last\_IO\_Error | 在通道上遇到的上一个 I/O 错误 | 
| Last\_SQL\_Error | 在通道上遇到的上一个 SQL 错误 | 
| Source\_Log\_File | 正在从源读取的当前二进制日志文件 | 
| Exec\_Source\_Log\_Pos | 二进制日志中 SQL 线程已应用的位置 | 

### 使用 CloudWatch 指标
<a name="AuroraMySQL.Replication.MultiSource.Monitoring.CloudWatch"></a>

监控每个复制通道的 `ReplicationChannelLag` CloudWatch 指标。该指标提供每个通道的复制滞后数据，期间为 60 秒，有效期为 15 天。要查找复制通道滞后，请使用 Aurora 数据库集群实例标识符和复制通道名称作为维度。您可以配置 CloudWatch 警报，以便在滞后超过特定的阈值时接收通知。有关更多信息，请参阅 [监控 Amazon Aurora 集群中的指标](MonitoringAurora.md)。

## 管理多源复制存储过程
<a name="AuroraMySQL.Replication.MultiSource.StoredProcedures"></a>

有关使用存储过程设置和管理多源复制通道的信息，请参阅[管理多源复制](mysql-stored-proc-multi-source-replication.md)。

## 注意事项和最佳实践
<a name="AuroraMySQL.Replication.MultiSource.Considerations"></a>

有关复制优化的一般建议，包括二进制日志格式、并行工作进程和增强型二进制日志，请参阅[优化 Aurora MySQL 的二进制日志复制](binlog-optimization.md)。以下注意事项特定于多源复制。

### 资源规划
<a name="AuroraMySQL.Replication.MultiSource.Considerations.Resources"></a>

运行多个复制通道时，副本上分配的复制线程总数为：（`replica_parallel_workers` \+ 1 个协调器线程）× 通道数。例如，默认的 `replica_parallel_workers` 值为 4 且有 10 个通道时，Aurora MySQL 会分配 50 个复制线程。根据您的源总吞吐量和通道计数，考虑使用更大的数据库实例类（例如 db.r6g.2xlarge 或更大）。每个通道接收相同数量的并行工作进程。MySQL 不支持为每个通道设置不同的并行工作进程计数。

### 避免冲突
<a name="AuroraMySQL.Replication.MultiSource.Considerations.Conflicts"></a>

MySQL 多源复制不提供冲突检测或解决方案。您必须确保来自不同源的更改不会发生冲突。常见策略包括：
+ 每个源都写入不同的数据库或一组表。
+ 使用复制筛选条件 (`replicate-do-db`) 以确保每个通道仅复制其负责的数据库。
+ 如果需要，可以使用 `replicate-rewrite-db` 选项将源中的架构名称重新映射到副本上的其它名称。

为防止直接连接到多源副本的应用程序发生写入冲突，请在 Aurora MySQL 集群上启用只读模式：`CALL mysql.rds_set_read_only(1);`

### 运营最佳实践
<a name="AuroraMySQL.Replication.MultiSource.Considerations.Operational"></a>
+ **一次一个通道**：一次对一个通道执行管理操作（例如配置更改、跳过错误或启动/停止复制）。避免从不同的连接同时更改多个通道。
+ **监控每个通道的滞后**：使用 `ReplicationChannelLag` CloudWatch 指标监控每个通道的复制滞后。
+ **源失效转移处理**：如果源数据库实例发生失效转移（例如，Amazon RDS Multi-AZ 失效转移），则复制通道可能会因出现 I/O 错误而停止。在源再次可用之后：
  + 调用 `mysql.rds_start_replication_for_channel` 以恢复复制。
  + 如果出现错误 1236（未找到日志文件），请调用 `mysql.rds_next_source_log_for_channel` 以便前进到下一个二进制日志文件。
+ **Aurora 写入器失效转移**：如果 Aurora MySQL 写入器实例失效转移到读取器，则复制通道配置将保留在集群的共享存储上。失效转移完成后，复制线程会在新的写入器实例上自动重启。

## 限制
<a name="AuroraMySQL.Replication.MultiSource.Limitations"></a>

以下限制特定于 Aurora MySQL 多源复制。有关 MySQL 多源复制的一般限制（例如每个通道的并行工作线程配置），请参阅 MySQL 文档中的 [MySQL Multi-Source Replication](https://dev.mysql.com/doc/refman/8.4/en/replication-multi-source.html)。
+ 仅 Aurora MySQL 8.4.8 及更高版本支持多源复制。
+ Aurora MySQL 支持为多源副本配置最多 **15 个通道**。

## 问题排查
<a name="AuroraMySQL.Replication.MultiSource.Troubleshooting"></a>

有关一般复制故障排除，请参阅 [ Amazon Aurora MySQL 复制问题](CHAP_Troubleshooting.md#CHAP_Troubleshooting.MySQL)。以下是特定于多源复制的故障排除说明。

### 快照还原后通道配置未还原
<a name="AuroraMySQL.Replication.MultiSource.Troubleshooting.Snapshot"></a>

数据库集群快照不包含多源通道配置。从快照还原后：
+ 使用 `mysql.rds_set_external_source_for_channel` 或 `mysql.rds_set_external_source_with_auto_position_for_channel` 重新配置每个通道。
+ 如果使用 GTID 自动定位，则副本可以自动从上次停下来的地方继续。
+ 如果使用二进制日志文件位置，请通过将源的二进制日志与已还原集群上最后应用的事务进行比较来确定当前位置。

### 一个或多个通道上的复制滞后增加
<a name="AuroraMySQL.Replication.MultiSource.Troubleshooting.Lag"></a>
+ 检查写入器实例的 CPU 和 I/O 指标。如果资源利用率较高，则纵向扩展实例类。
+ 考虑增加 `replica_parallel_workers` 以提高 SQL 线程吞吐量。
+ 确认通道上不存在可能阻止 SQL 线程的长时间运行的事务或 DDL 操作。
+ 检查是否存在冲突的筛选条件配置，此类配置可能会导致复制处理大量事件，然后将它们丢弃。

## 示例：使用三个源完成多源设置
<a name="AuroraMySQL.Replication.MultiSource.Example"></a>

以下示例演示如何将 Aurora MySQL 数据库集群配置为三个 RDS for MySQL 源实例的多源副本。

### 步骤 1：记录每个源上的二进制日志位置
<a name="AuroraMySQL.Replication.MultiSource.Example.Step1"></a>

连接到每个源并记录二进制日志坐标：

```
-- On source 1 (orders-db.xxxxx.us-east-1.rds.amazonaws.com)
SHOW BINARY LOG STATUS;
-- Result: mysql-bin-changelog.000045, Position: 3892

-- On source 2 (inventory-db.xxxxx.us-east-1.rds.amazonaws.com)
SHOW BINARY LOG STATUS;
-- Result: mysql-bin-changelog.000012, Position: 1567

-- On source 3 (analytics-db.xxxxx.us-east-1.rds.amazonaws.com)
SHOW BINARY LOG STATUS;
-- Result: mysql-bin-changelog.000078, Position: 9421
```

### 步骤 2：从每个源导入数据
<a name="AuroraMySQL.Replication.MultiSource.Example.Step2"></a>

```
# Import from source 1
mysqldump --databases orders_db --single-transaction --compress \
 -u admin -p --host=orders-db.xxxxx.us-east-1.rds.amazonaws.com | \
 mysql --host=my-aurora-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com -u admin -p

# Import from source 2
mysqldump --databases inventory_db --single-transaction --compress \
 -u admin -p --host=inventory-db.xxxxx.us-east-1.rds.amazonaws.com | \
 mysql --host=my-aurora-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com -u admin -p

# Import from source 3
mysqldump --databases analytics_db --single-transaction --compress \
 -u admin -p --host=analytics-db.xxxxx.us-east-1.rds.amazonaws.com | \
 mysql --host=my-aurora-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com -u admin -p
```

### 步骤 3：配置并启动复制通道
<a name="AuroraMySQL.Replication.MultiSource.Example.Step3"></a>

连接到 Aurora MySQL 写入器实例：

```
-- Configure channel for source 1 (orders)
CALL mysql.rds_set_external_source_for_channel(
 'orders-db.xxxxx.us-east-1.rds.amazonaws.com',
 3306, 'repl_user', 'password',
 'mysql-bin-changelog.000045', 3892, 0, 'orders_channel'
);

-- Configure channel for source 2 (inventory)
CALL mysql.rds_set_external_source_for_channel(
 'inventory-db.xxxxx.us-east-1.rds.amazonaws.com',
 3306, 'repl_user', 'password',
 'mysql-bin-changelog.000012', 1567, 0, 'inventory_channel'
);

-- Configure channel for source 3 (analytics)
CALL mysql.rds_set_external_source_for_channel(
 'analytics-db.xxxxx.us-east-1.rds.amazonaws.com',
 3306, 'repl_user', 'password',
 'mysql-bin-changelog.000078', 9421, 0, 'analytics_channel'
);

-- Start all channels
CALL mysql.rds_start_replication_for_channel('orders_channel');
CALL mysql.rds_start_replication_for_channel('inventory_channel');
CALL mysql.rds_start_replication_for_channel('analytics_channel');
```

### 步骤 4：验证复制状态
<a name="AuroraMySQL.Replication.MultiSource.Example.Step4"></a>

```
SHOW REPLICA STATUS\G
```

对每个通道进行确认：
+ `Replica_IO_Running: Yes`
+ `Replica_SQL_Running: Yes`
+ `Seconds_Behind_Source: 0`（或较低的值）

## 相关资源
<a name="AuroraMySQL.Replication.MultiSource.RelatedResources"></a>
+ [MySQL Multi-Source Replication](https://dev.mysql.com/doc/refman/8.4/en/replication-multi-source.html)：MySQL 文档
+ [Aurora 与 MySQL 之间或 Aurora 与其他 Aurora 数据库集群之间的复制（二进制日志复制）](AuroraMySQL.Replication.MySQL.md)：Aurora 用户指南
+ [优化 Aurora MySQL 的二进制日志复制](binlog-optimization.md)：Aurora 用户指南
+ [使用 Aurora MySQL 配置复制筛选条件](AuroraMySQL.Replication.Filters.md)：Aurora 用户指南
+ [使用基于 GTID 的复制](mysql-replication-gtid.md)：Aurora 用户指南