mysql 8.0多源复制仅支持并行拉取多主binlog并独立回放,不自动汇总数据;业务级汇聚需应用层或中间层实现,配置核心是确保通道命名唯一、gtid开启、row格式、只读保护及状态逐通道检查。

MySQL 8.0 的多源复制本身不“汇总”数据,它只是让一个从库并行拉取多个主库的 binlog 并各自回放;真正要实现业务级汇聚(比如把 orders、users、logs 三张同名表合并进一张宽表),必须靠你在应用层或中间层做逻辑处理。配置只解决“能拉、不冲突、不丢事务”这三件事。
必须用 CHANGE REPLICATION SOURCE TO 显式指定 FOR CHANNEL
MySQL 8.0+ 已彻底移除 CHANGE MASTER TO,所有通道都必须命名。漏写 FOR CHANNEL 'xxx' 或重复使用同一 channel 名,会直接报错:ERROR 3079 (HY000): Multiple channels exist, please specify channel name 或 ERROR 3077 (HY000): Channel name already exists。
- 每个通道名必须语义清晰且唯一,例如
'prod_orders'、'analytics_logs',避免用'master1'这类无上下文命名 - 通道名大小写敏感,
'Orders'和'orders'是两个不同通道 - 建通道前必须先执行
STOP REPLICA;,否则并发修改可能触发ERROR 3080
binlog_format = ROW 和 GTID_MODE = ON 是硬性前提
只要有一个主库的 binlog_format 是 STATEMENT 或 MIXED,对应通道就会静默卡住:SQL 线程状态变成 Waiting for dependent transaction to commit,Seconds_Behind_Source 持续增长,但你看不到明确报错。
- 检查方式:在各主库上执行
SHOW VARIABLES LIKE 'binlog_format';和SELECT @@GLOBAL.GTID_MODE; - 修改方式(MySQL 8.0+):
SET PERSIST binlog_format = 'ROW';+ 重启mysqld;仅SET GLOBAL重启后失效 - 启用 GTID 后,
SOURCE_AUTO_POSITION = 1是强制的,不能再填SOURCE_LOG_FILE/SOURCE_LOG_POS,否则报ERROR 3077
SHOW REPLICA STATUS 默认只显示空通道,查状态必须带 FOR CHANNEL
这是最常被忽略的操作陷阱:你执行 SHOW REPLICA STATUS; 看到 Replica_IO_Running: Yes,就以为所有通道都正常——其实它只反映默认空字符串通道的状态,其他通道完全不显示。
- 查单个通道:
SHOW REPLICA STATUS FOR CHANNEL 'prod_orders'; - 重点关注字段:
Retrieved_Gtid_Set(是否持续增长)、Executed_Gtid_Set(是否跟上)、Seconds_Behind_Source(延迟秒数)、Replica_SQL_Running_State(当前 SQL 线程状态) - 启动也必须带通道名:
START REPLICA FOR CHANNEL 'prod_orders';,只执行START REPLICA;只会启动默认空字符串通道
多源复制无法解决表名/主键冲突,必须靠外部逻辑控制
多源复制不会重命名表、不会合并同名表、不会处理主键冲突。如果两个主库都往 db1.t_user 插入自增 ID,且没做 auto_increment_offset/auto_increment_increment 隔离,从库大概率报 Duplicate entry 'X' for key 'PRIMARY'。
- 所有上游主库的
auto_increment_increment设为相同值(如 10),auto_increment_offset各不相同(如 1, 2, 3…) - 确保从库对应表设为
READ ONLY,禁止任何写入(包括临时修复脚本) - 禁用从库的并行复制:
SET GLOBAL replica_parallel_workers = 0;,多源下开启反而容易因协调点阻塞导致全部通道延迟飙升 - 定期检查各通道的
Retrieved_Gtid_Set是否连续增长,跳跃意味着已丢事务
真正难的不是配置命令,而是确认每个主库的 server_id 全局唯一、每个通道的 SOURCE_HOST DNS 可达、每张目标表在从库上是否真的只读——这些细节一旦漏掉,问题往往表现为“看起来跑着,其实早就不动了”。











