连载中 14/20

数据迁移(上):双写方案的全貌

2026-07-25 · 4010 阅读 · 0 评论 · 0 赞

为什么只剩双写一条路

把几亿行数据从老库搬到新的分片架构,先算时间账:全量拷贝按每小时千万行的安全速率,几天起步;期间线上业务还在持续写入——搬完的那一刻,数据已经过时了几天。停机迁移能终结这个死循环,但业务批不出这个窗口。于是唯一现实的方案浮出水面:老库照常服役,新库并行同步,两边数据追平后灰度切流。这套方案拆成四个阶段:存量同步 → 增量双写 → 全量校验 → 灰度切流,本篇讲前两个,校验与切流留给下一篇。

阶段一:存量同步

存量搬迁的技术选型不重要(dumponly、DataX、自研分批脚本都行),纪律才重要,三条:限速——搬迁查询压在源库安全水位以下(用空闲时段加限速批次,别把主库 IO 打满拖垮线上业务);断点续传——按主键或时间片分批,每批记水位,挂了从水位继续;与新库写入兼容——迁移程序写入新分片时绕过业务逻辑直接落库,但 ID、分片基因必须与线上规则严格一致,否则全量校验一地鸡毛。

阶段二:增量双写

存量在搬,增量在写——双写就是把这段「追赶期」的数据变更同时送达两个库。实现方式两条路,侵入度与可控性各有取舍:业务代码双写——在写路径里同时写老库与新分片,逻辑直白、排查直观,但每个写接口都要改、要防两库写一半(各自的本地事务,失败要靠补偿对账兜),代码侵入大;订阅 binlog 同步——老库仍是唯一写入口,binlog 被订阅程序捕获后转换成新分片的写入,业务代码零改造。binlog 链路天然有序、可靠,代价是多一套同步组件要维护:

业务 ──写入──> 老库(唯一权威) ──binlog──> 订阅同步服务
                                          ├─ 解析变更(表/行/操作)
                                          ├─ 按分片规则路由到新分片
                                          └─ 写入新库(失败进重试队列)

工程里更常见的组合是binlog 同步打底,双写只在关键路径做保险。无论哪种,两条纪律要立住:以老库为权威——双写期间老库的数据永远是基准,新库只许追不许改业务语义;失败只告警不阻塞——新库写失败绝不能影响线上业务,靠重试队列加对账修复,这是双写期间业务零感知的代价交换。

追赶与追平

存量同步与增量双写有个鸡生蛋的先后问题:存量搬了三天,期间的变更怎么办?标准答案是先启增量双写,再跑存量同步——双写把「此刻起」的变更送达新库,存量任务负责「此刻之前」的历史,两条线在时间上无缝衔接;重叠的少数边界数据,靠新库的幂等写入(主键冲突即跳过或覆盖)自然去重。当存量搬迁完成、双写延迟稳定趋近于零,就到了下一阶段:全量校验——数据「看起来追平」和「真的追平」之间,隔着一套严谨的核对体系,下一篇展开。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#数据迁移#双写#binlog同步#存量搬迁#增量同步

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞