Canal 实例重启后,binlog 位点比实际落后了 3 小时。下游宽表多出 21840 行重复记录,同一个主键能看到两条。乍看像缓存或者权限的锅,追下去往往不是。
SHOW MASTER STATUS; SHOW BINARY LOGS; SELECT id, COUNT(*) c FROM dwd_order GROUP BY id HAVING c > 1 LIMIT 20;
追下去是这么回事:位点信息只存在本地 meta 文件里,容器重建把文件覆盖回镜像里的旧值。Canal 从旧位点重新解析,中间这段变更被再投一次。下游只做 insert 没做 upsert,重复就直接落表。
「binlog 位点回退」这类改动最怕改一半,回滚脚本先准备好,再动生产。一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。
先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。别只看报错的最后一行,往上看几行,真正的起因通常在上面。
具体做法是,把 meta 文件挂到持久卷 不要留在容器可写层;启动前用 SHOW MASTER STATUS 核对位点 差太多就人工对齐;下游写入改成按主键 upsert;补一条按主键去重的清洗 SQL 把重复行删掉。
验收就看一点,重启后位点从持久卷读出 和主库当前文件只差一个 binlog 重复行清零。
