mysql 8.0多源复制仅实现并行拉取与回放多个主库binlog,不自动汇总数据;必须显式指定for channel命名通道,强制要求所有主库binlog_format=row且开启gtid,否则静默失败;状态查看、启停及过滤均需按通道操作,无法解决表名/主键冲突或业务级聚合,仅提供可靠管道。

MySQL 8.0 的多源复制本身不“汇总”数据,它只是让一个从库并行拉取多个主库的 binlog 并各自回放;真正要实现业务意义上的数据汇总(比如把订单、日志、用户三张同名表合并到一张宽表),必须靠你在应用层或中间层做逻辑处理。配置本身只解决“能拉、不冲突、不丢事务”这三件事。
必须用 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'这类无上下文命名 - 配置前务必先执行
STOP REPLICA;,否则并发修改可能触发ERROR 3080 - 启动时也必须带通道名:
START REPLICA FOR CHANNEL 'prod_orders';,只执行START REPLICA;只会启动默认空字符串通道
binlog_format = ROW 和 GTID 不是可选项,是硬性前提
只要有一个主库的 binlog_format 是 STATEMENT 或 MIXED,对应通道就会静默卡住:SQL 线程状态变成 Waiting for dependent transaction to commit,Seconds_Behind_Source 持续增长,但你看不到明确报错。
- 检查方式:
SHOW VARIABLES LIKE 'binlog_format';—— 主库上查,不是从库 - 修改方式(MySQL 8.0+):
SET PERSIST binlog_format = 'ROW';,然后重启mysqld;仅SET GLOBAL重启后失效 - 启用 GTID 后,
SOURCE_AUTO_POSITION = 1是强制的,不能再填SOURCE_LOG_FILE/SOURCE_LOG_POS,否则报ERROR 3077: When @@GLOBAL.GTID_MODE = ON, all replication channels must use AUTO_POSITION
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(注意它只对本通道有意义) - 批量查看所有通道状态:
SELECT CHANNEL_NAME, SOURCE_UUID, SERVICE_STATE, RECEIVED_TRANSACTION_SET FROM performance_schema.replication_connection_status;
auto_increment 冲突和表名重叠必须手动隔离
多源复制不会帮你解决主键冲突或库表名冲突。两个主库都往 orders 表插数据,即使设置了 auto_increment_offset,只要从库自己曾对该表执行过 INSERT,自增计数器就可能错乱,最终报 Duplicate entry 'X' for key 'PRIMARY'。
- 上游所有主库统一设:
auto_increment_increment = 10,auto_increment_offset各不相同(如 1/2/3) - 从库对应表必须设为
READ ONLY:ALTER TABLE orders READ ONLY;,禁用任何写入 - 如果主库库名不同(如
shop_db.orders和log_db.orders),需用replicate_rewrite_db重写库名,避免覆盖:CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB = (('shop_db', 'merged_shop'), ('log_db', 'merged_log')) FOR CHANNEL 'prod_orders';
真正难的不是配通,而是确认“哪些表允许被多源写入”“哪些字段需要去重/合并/转换”。MySQL 原生不做这些,它只保证 binlog 能按序回放。一旦业务逻辑要求跨源聚合,就得在从库之上加一层物化视图、Flink CDC 或定制同步脚本——多源复制只是管道,不是ETL引擎。











