MySQL多源复制需5.7.17+版本,主从server-id唯一,从库设master_info_repository和relay_log_info_repository为TABLE,启用GTID,各主库配置独立通道并分别启停复制。

确认 MySQL 版本和基础参数是否达标
MySQL 5.7.5+ 才真正支持多源复制,但低于 5.7.17 的版本存在 channel 解析缺陷,容易在执行 CHANGE REPLICATION SOURCE TO ... FOR CHANNEL 时误报 ERROR 1235 (HY000) 这类语法错误——实际是解析 FOR CHANNEL 失败导致的连锁误判。
必须检查并确保以下几项:
-
SELECT VERSION();返回至少5.7.17(推荐5.7.28+或8.0.22+) - 所有主库和从库的
server_id全局唯一(不能重复,也不能为 0) - 从库需启用
master_info_repository = TABLE和relay_log_info_repository = TABLE,否则通道元数据无法持久化 - 强烈建议开启
gtid_mode = ON和enforce_gtid_consistency = ON,避免 position 手动管理出错
为每个主库配置独立 channel(注意命名与语法)
从库上每添加一个主库,就必须显式指定非空 channel 名,且不能省略 FOR CHANNEL 'xxx'。MySQL 5.7+ 已统一用 CHANGE REPLICATION SOURCE TO,CHANGE MASTER TO 在新版本中虽兼容但不推荐。
例如配置两个主库:
CHANGE REPLICATION SOURCE TO SOURCE_HOST = '192.168.1.10', SOURCE_USER = 'repl_a', SOURCE_PASSWORD = 'pwd_a', SOURCE_AUTO_POSITION = 1 FOR CHANNEL 'src_a'; CHANGE REPLICATION SOURCE TO SOURCE_HOST = '192.168.1.11', SOURCE_USER = 'repl_b', SOURCE_PASSWORD = 'pwd_b', SOURCE_AUTO_POSITION = 1 FOR CHANNEL 'src_b';
常见错误:
- 漏写
FOR CHANNEL→ 默认通道被覆盖,其余通道静默丢失 - channel 名为空或含非法字符(如空格、斜杠)→ 报错
ERROR 1238 (HY000) - 复用同一
SOURCE_USER密码但未在对应主库创建该用户 → IO 线程连不上,日志只显示Could not initialize master info structure,无具体原因提示
逐个启停与状态检查,别信“START REPLICA”一把梭
执行完所有 CHANGE REPLICATION SOURCE TO ... FOR CHANNEL 后,START REPLICA(无 FOR CHANNEL)只会启动默认通道(空名 channel),其他通道完全不动,且 SHOW REPLICA STATUS 也只返回默认通道状态——这是最常被忽略的故障点。
正确做法是:
- 分别启动:
START REPLICA FOR CHANNEL 'src_a';、START REPLICA FOR CHANNEL 'src_b'; - 分别查状态:
SHOW REPLICA STATUS FOR CHANNEL 'src_a'\G,看IO_Running和SQL_Running是否为Yes,以及Seconds_Behind_Source - 分别停用:
STOP REPLICA FOR CHANNEL 'src_b';,避免误停其它通道
监控可进一步查 performance_schema.replication_connection_status 和 replication_applier_status_by_coordinator 表,比 SHOW 命令更实时。
数据冲突不是自动解决的,得靠架构隔离
多源复制不会合并、去重或协调事务。如果 src_a 和 src_b 都往同一个表 log.events 插入主键为 123 的记录,从库必然卡住,报错 ERROR 1062 (23000): Duplicate entry '123' for key 'PRIMARY',且 SQL_Running = No。
并行复制参数(如 replica_parallel_workers)只影响单通道内事务调度,对跨通道冲突毫无作用。
可行方案只有两种:
- 业务层写隔离:不同主库写不同库名(如
app_a.ordersvsapp_b.orders),或加前缀(src_a_user/src_b_user) - 主库侧路由 + 从库重映射:用
replicate_rewrite_db将orders→src_a_orders,但注意它不支持正则,且仅对USE语句生效,DDL 无效
最后提醒一句:多源从库务必设 read_only = ON,否则本地写入会污染 GTID 集合,导致后续同步不可逆中断。


















