真实给一个replica配上两个独立的复制channel,接入两个互不知晓的source,验证多源复制真实能不能把数据汇流到一起,以及路上会撞到什么坑。
代码-- 真实第三个独立实例,server-id=3 mysqld --server-id=3 --log-bin=source2-bin --gtid-mode=ON ... -- replica上,真实配一个独立命名的channel CHANGE REPLICATION SOURCE TO SOURCE_HOST='127.0.0.1', SOURCE_PORT=19312, ... FOR CHANNEL 'from-source2'; START REPLICA FOR CHANNEL 'from-source2';
Worker 1 failed executing transaction '...':1 ... Error 'Operation CREATE USER failed for 'repl'@'%' (User account already exists)'
第二个source上同样执行了CREATE USER 'repl'@'%'(为了给它自己的复制账号),这条DDL真实作为binlog事件的一部分被channel 2复制了过来——但repl这个账号早就已经因为channel 1的第一次复制真实存在于replica上了,两个channel的历史DDL真实在同一个实例上产生了冲突。这个坑真实印证了多源复制的一个现实约束:接入同一个replica的多个source,如果各自的历史操作里创建过同名对象(账号、数据库、表),真实有很大概率会在初次全量同步时撞车。
代码SET GTID_NEXT='...:1'; BEGIN; COMMIT; SET GTID_NEXT='AUTOMATIC'; -- 真实跳过冲突事务 START REPLICA FOR CHANNEL 'from-source2';
-- source1(19310)写入kiwi,source2(19312)写入SKU-200 SELECT 'channel 1' src, item, qty FROM shop.orders WHERE item='kiwi' UNION ALL SELECT 'channel 2', sku, qty FROM inventory.stock WHERE sku='SKU-200'; src item qty channel 1 kiwi 6 channel 2 SKU-200 75
每一步都是本文上面用真实三节点复制环境跑出来的原始结果。
CHANGE REPLICATION SOURCE ... FOR CHANNEL + performance_schema.replication_connection_status