跨库同步中断后应查迁移工具记录的源库位点(如binlog_file和binlog_position),而非SHOW MASTER/SLAVE STATUS;需确保目标表有全覆盖唯一键、ROW格式binlog、GTID配置一致,并监控三时间轴避免幻觉位点。
MySQL跨库同步中断后怎么找断点
靠 show master status 或 show slave status 查当前位点,根本不管用——那是主库或从库自己的位置,跨库迁移时源和目标压根不在一个复制链上。真正要盯的是迁移工具记录的「最后成功写入目标库的源库位点」,比如 binlog_file 和 binlog_position 这两个字段,必须从迁移任务的元数据表(如 checkpoint 表)或日志文件里捞。
常见错误现象:重启任务后重复写入、主键冲突、跳过大量已同步数据。原因往往是把源库的 Exec_Master_Log_Pos 当成续传起点,但目标库没对应事务,位点不等价。
- 使用场景:用
mysqldump+mysqlbinlog手动拼接,或基于canal/debezium的自研管道 - 参数差异:
canal依赖zk存储cursor,debezium用Kafka offset,而纯脚本方案得自己维护checkpoint表 - 性能影响:每次写入都更新
checkpoint表会拖慢吞吐,建议批量提交后统一刷一次,但得确保幂等
如何保证跨库续传时的数据幂等
断点续传最怕重放——同一行变更被写两次,尤其是 INSERT ... ON DUPLICATE KEY UPDATE 这类语句,如果没对齐业务主键和唯一约束,很容易把 UPDATE 变成无意义的覆盖或漏更新。
核心不是“怎么避免重放”,而是“重放了也不出错”。关键在目标表必须有稳定、全覆盖的唯一键(不能只靠 id 自增),且迁移语句必须显式指定冲突策略。
- 常见错误现象:
Duplicate entry '123' for key 'PRIMARY'报错中断,或UPDATE没生效却没报错 - 使用场景:从 MySQL 5.7 迁到 8.0,或从 RDS 迁到自建库,DDL 不一致导致唯一索引缺失
- 兼容性影响:MySQL 8.0 支持
INSERT ... ON DUPLICATE KEY UPDATE多列判断,但 5.7 不支持函数索引,别指望用JSON_EXTRACT做唯一约束
异构迁移中 binlog 格式与 GTID 的坑
源库开 binlog_format=ROW 是底线,STATEMENT 格式下跨库续传基本不可靠——函数、临时表、非确定性语句都会让目标端解析错乱。GTID 更麻烦:目标库若开启 gtid_mode=ON,但源库没开,或者两边 server_uuid 冲突,SET GTID_NEXT 会直接拒绝执行。
真实情况是:很多线上库开着 GTID 却没清理过 gtid_purged,一断线再连,CHANGE MASTER TO 就报 Cannot replicate because the master purged required binary logs。
- 参数差异:
binlog_row_image=FULL必须开,否则UPDATE缺少旧值,目标端做不了对比更新 - 性能影响:
ROW格式日志体积大,网络传输和解析压力翻倍,但这是换数据一致性的必要成本 - 检查命令:
SELECT @@binlog_format, @@gtid_mode, @@server_uuid;,两边都得跑一遍
目标库延迟高时怎么安全续传
不是所有“中断”都是挂了——更常见的是目标库写入慢,导致迁移程序以为失败而退出。这时候硬切到新位点,等于跳过积压的 binlog,数据就永远不一致了。
正确做法是先确认积压是否真实可追:查源库 mysql-bin.000001 是否还存在,用 mysqlbinlog --base64-output=DECODE-ROWS -v 抽样看事件内容;再查目标库最近一条写入时间,和源库当前 binlog_position 对比时间差。
- 常见错误现象:重启任务后发现目标库少了 2 小时数据,但源库日志已被 purge
- 使用场景:目标库用了低配 SSD,或开了太多触发器/外键约束,单条
INSERT耗时超 100ms - 可操作建议:加监控项
lag_seconds(源库当前时间 - 最后一条事件时间),超过阈值自动告警而非自动续传
跨库续传真正的复杂点不在代码怎么写,而在你得同时盯着三个时间轴:源库 binlog 生成时间、迁移程序读取时间、目标库落库时间——三者不同步,任何“位点”都是幻觉。

















