mysql 5.7多源复制仅同步binlog,不提供sql聚合能力;真正聚合需手动在从库用join/union/view等实现,且须确保表结构兼容、库表名不冲突。

MySQL 5.7 的多源复制本身不提供 SQL 聚合能力,它只负责把多个主库的 binlog 拉过来、重放进同一个从库;真正的聚合必须靠你在从库上手动写 JOIN / UNION / VIEW / 存储过程来实现——而且前提是表结构兼容、库名或表名不冲突。
多源复制配置必须启用 TABLE 存储元数据
否则 START SLAVE FOR CHANNEL 会失败,甚至导致 relay log 错乱。这是最常被忽略的硬性前提:
-
master-info-repository=TABLE和relay-log-info-repository=TABLE必须在从库my.cnf中显式设置,不能依赖默认值FILE - 这两个参数不可动态修改后立即生效:需重启 mysqld,或先
STOP SLAVE再执行SET GLOBAL并验证表mysql.slave_master_info和mysql.slave_relay_log_info是否可写 - 如果之前用过 FILE 模式且未清理旧文件(如
master.info),启动时可能读取错误位置,引发ERROR 1236
不同主库同名表合并前必须重命名或过滤
比如 order_db.payment 和 finance_db.payment 都同步到从库,直接应用会报 ERROR 1050 (42S01): Table 'payment' already exists:
- 用
replicate-rewrite-db重写库名(例如replicate-rewrite-db = 'order_db->order_master'),但注意:该参数只作用于库级,且必须在CHANGE MASTER TO ... FOR CHANNEL之前配置,重启才生效 - 更灵活的做法是用
replicate-ignore-table过滤掉冲突表,再用mysqldump --databases order_db --tables payment --skip-triggers --no-create-info | sed 's/`payment`/`order_payment`/g'手动导入重命名后的表 -
replicate-do-db是全局生效的,对所有 channel 一视同仁,不适合差异化控制;应改用 per-channel 过滤:CHANGE REPLICATION FILTER replicate_do_table = ('order_db.orders') FOR CHANNEL 'order_chan';
GTID 模式下启动 channel 容易卡在 “Waiting for master to send event”
这不是网络问题,而是 GTID 集合不匹配导致 SQL thread 不敢执行:
- 确保每个主库的
gtid_mode=ON、enforce-gtid-consistency=ON,且从库也开启——三者缺一不可 - 导入初始数据时,必须用
mysqldump --set-gtid-purged=ON(而非--master-data=2),否则从库的gtid_executed与主库不一致 - 查状态时重点看:
SELECT * FROM performance_schema.replication_connection_status WHERE CHANNEL_NAME = 'xxx'\G,若SOURCE_UUID为空或LAST_HEARTBEAT_TIMESTAMP停滞,说明 IO thread 未真正连接上 - 不要依赖
SET GLOBAL sql_slave_skip_counter = 1:GTID 模式下该语句被禁用,出错只能用SET GTID_NEXT='xxx'; BEGIN; COMMIT;注入空事务跳过
聚合查询前必须确认表引擎、字符集、时间类型完全一致
哪怕只是 TIMESTAMP vs DATETIME 或 utf8mb4_0900_as_cs vs utf8mb4_general_ci,JOIN 时都可能触发隐式转换、索引失效或结果偏差:
- 检查方式:
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA IN ('order_master', 'user_master'); - 跨库 JOIN 无法使用从库的并行 SQL thread 加速,全靠单线程执行,大表关联务必加覆盖索引
- 不要在从库上写入任何业务数据——
log-slave-updates=ON是为了支持级联,不是让你当普通实例用;一旦误写,GTID 冲突会导致整个复制链路中断
最麻烦的不是配置步骤,而是表结构演化:一个主库加了字段、另一个没加,或者某次 DDL 只在部分主库执行,从库重放时就会停在那个语句上。这类问题不会报错,只会静默卡住,得靠定期比对 information_schema.COLUMNS 和监控 Seconds_Behind_Master 的突变来发现。











