replicate_rewrite_db对多源复制无效,因其是全局变量且不支持channel级配置;所有通道共用同一映射,导致同名库表重写冲突。

MySQL多源复制中同名表无法自动隔离,直接同步必然冲突;必须在主库侧改名、或从库侧手动建库+表级过滤,replicate_rewrite_db 在多源场景下完全无效。
为什么 replicate_rewrite_db 对多源复制不起作用
该参数是全局变量,不支持 channel 级别配置。执行 CHANGE REPLICATION FILTER replicate_rewrite_db = ((master_db, slave_db)) FOR CHANNEL 'chan1' 会直接报错 ERROR 1238 (HY000): Variable 'replicate_rewrite_db' is a GLOBAL variable。即使设成 SET GLOBAL replicate_rewrite_db = ('orders', 'orders_us'),所有 channel 都共用这一映射,无法区分不同主库来源——结果就是两个 master 的 orders 库都试图重写成同一个 orders_us,仍触发 ERROR 1050 (42S01): Table 'orders' already exists。
真正能落地的三种方案及实操要点
绕过 replicate_rewrite_db,从源头或结构上隔离:
-
主库侧改名(推荐):每个 master 使用带地域/业务前缀的库名,如
orders_us、orders_jp、users_core。避免从库做任何重写逻辑,DDL 完全自治,无歧义 -
从库手动建库 +
replicate_do_table过滤:- 先停对应 channel:
STOP SLAVE FOR CHANNEL 'master2' - 手动创建目标库:
CREATE DATABASE orders_v2 - 只允许同步指定表:
CHANGE REPLICATION FILTER replicate_do_table = ('orders_v2.orders') FOR CHANNEL 'master2' - 注意:
replicate_do_table不重写语句中的库名,它只是“开关”——主库 binlog 里仍是INSERT INTO orders,所以必须确保该语句执行时默认库已是orders_v2(靠USE orders_v2或连接时指定)
- 先停对应 channel:
-
DDL 统一由中间层下发:禁用所有 master 的
log_slave_updates,只允许一个“DDL Master”生成库表变更,其余 master 仅承担业务写入。这样从库收到的所有 DDL 都来自单一源头,天然规避重复建表
最容易被忽略的坑:relay log 文件名冲突
多个 channel 若共用默认 relay-log 前缀(如都叫 relay-bin.000001),会导致中继日志写入混乱,轻则同步卡住,重则数据错乱。必须为每个 channel 显式指定唯一前缀:
CHANGE MASTER TO RELAY_LOG_FILE='relay_order.000001' FOR CHANNEL 'order_master'; CHANGE MASTER TO RELAY_LOG_FILE='relay_user.000001' FOR CHANNEL 'user_master';
这个细节在 SHOW SLAVE STATUS FOR CHANNEL 'xxx' 中不会直接报错,但会在 error log 里反复出现 Failed to open relay log 或 Relay log read failure,排查成本极高。











