半夜两点,运维老张盯着屏幕上的同步延迟数字,从三位数跳到四位数,手心全是汗。这是他们团队第三次尝试做核心库的版本升级,前两次都因为业务无法接受停机窗口而回滚。他跟我吐槽说,这年头数据库升级比给飞行中的飞机换引擎还难。这话听着夸张,但做过的都懂——业务24小时在线,交易不能断,数据不能丢,唯一能接受的就是“无感”。增量迁移,就是给这架飞机换引擎时,保证客舱里咖啡不洒出来的那套手艺。

很多人一听“增量迁移”,第一反应是找个工具把binlog或者redo log同步过去就行。真这么简单,市面上一半的DBA都得失业。增量迁移的难点从来不在“同步”这个动作,而在“一致性”这条底线。你想想,目标库的数据一直在追源库,可源库的业务还在不停写,两边就像两个跑步的人,一个在前面跑,一个在后面追,追的人永远差那么几步。关键问题是,你什么时候告诉业务“可以切换了”?如果切换的瞬间,目标库还差几秒的数据,那这几秒的交易就丢了,对金融、电商这种行业来说,这就是事故。
所以真正的增量迁移,从来不是“同步完了切一下”这么简单,而是一个分阶段的收敛过程。第一阶段是全量拷贝,把源库的历史数据导到目标库,这个阶段业务无感,压力主要在IO和带宽上。第二阶段是增量追平,让目标库通过解析日志持续追上源库的新写入。这时候你观察的核心指标不是“追没追上”,而是“延迟趋势”——如果延迟曲线是收敛的,比如从五分钟慢慢压到三秒,说明能追平;如果延迟像心电图一样波动,忽高忽低,那就要排查是不是目标库的写入性能有瓶颈,或者源库的业务高峰跟同步任务撞了车。
我见过最典型的翻车场景,是有人在业务大促前一天做迁移。白天看着延迟还行,到了晚上八点流量起来,源库的写TPS翻了三倍,同步任务直接被打爆,日志积压了几百万条。这时候你怎么办?回滚?全量数据已经导过去了,回滚成本高得吓人。硬着头皮继续?延迟追不上,业务那边已经开始报查询超时了。所以说,增量迁移的第一个实战原则是:选窗口,别硬扛。哪怕业务说24小时都有流量,你也得找一天中相对平缓的时段来启动增量同步,给系统留出追赶的余量。
除了时机,还有一块硬骨头是“数据校验”。很多团队觉得,同步工具没报错,就代表数据没丢。这个想法特别危险。日志解析类的同步,最怕的是字段类型映射出了偏差——比如源库是datetime,目标库是timestamp,时区没对齐,差出来的8个小时你肉眼根本看不出来。还有自增主键冲突,源库用AUTO_INCREMENT,目标库之前手动插过数据,序列没调对,同步到一半直接主键撞车,任务就停了。所以增量迁移必须配上“抽样校验”和“全量对账”两板斧。抽样校验在迁移过程中持续做,每同步一小时就随机抽几百条记录比对关键字段;全量对账在切换前做一次,把源库和目标库的表逐行比对哈希值,这一步虽然耗时,但是兜底,能拦住绝大多数“工具说成功但数据不对”的暗坑。
工具选型也是个能聊三天三夜的话题。开源的有DataX、Canal、Debezium,商业的也有各云厂商的DTS。我的建议是,别迷信名气,别迷信“一键配置”,关键看你们的业务复杂度和团队维护能力。如果库表结构简单,字段类型规整,Canal加个消费端就能搞定。如果业务里有存储过程、触发器、自定义函数这些花活,那就要慎重了——大多数日志解析工具只同步DML,不处理存储过程内部的逻辑,源库跑了个存储过程改了二十张表,目标库可能只同步了其中几张,这种不一致是静默的,比报错还可怕。这时候你得考虑“双写方案”,在应用层同时写源库和目标库,等追平后再切流,虽然改动大,但胜在可控。
还有一件事,很多人到切换那一刻才想起来——序列和自增值的同步。你以为数据都追平了,一切万事大吉,结果切过去之后新业务写入,主键直接冲突,应用层报错报警,你才发现源库的自增ID已经走到一千万,目标库还停在八百万。这种情况不是数据同步的问题,是元数据没有同步。所以增量迁移的方案里,必须把“序列迁移”单独列出来,切换前把源库的序列值查出来,手动或脚本更新到目标库里。这个步骤不需要多高的技术含量,就是细心,但往往就是这种不起眼的细节决定成败。
再往深一层说,增量迁移最考验人的不是技术,是“回滚预案”。很多团队把精力都放在“怎么迁成功”上,很少有人认真想“迁失败了怎么退回来”。但实战中,切换后两小时发现问题要回滚的场景太常见了。聪明的做法是,切换前保留源库的只读权限,把源库的写入停掉,但别关库,这样一旦目标库有问题,还能立刻把流量切回源库,数据一条不丢。还有一种更稳妥的玩法,叫“灰度切换”——先让5%的读流量打到目标库,观察一段时间,再慢慢扩大比例,才把写流量切过去。虽然时间拉长了,但每一步都有回退的余地,反而比一把梭更稳。
说到这,想起之前有个朋友做金融核心系统迁移,他们用了整整三天做增量追平,延迟压到两秒以内,然后在一个周末的凌晨,把写流量切了过去。切换后他们没急着撤掉源库,而是让双写又跑了一天,第二天对账发现目标库多了一条数据,源库没有——查了半天,是某个应用在切换瞬间重试了请求,导致重复插入。好在双写机制兜住了,他们手工清理了那条脏数据。这个案例我想说的是,增量迁移的终点不是“切过去”,而是“切过去之后还能稳得住”。双写、对账、灰度,这些看似繁琐的步骤,都是给“稳”字上的保险。
回到老张那个半夜的焦虑。他后来告诉我,那次迁移最终成功了,靠的不是某个神器,而是一张写满检查项的Excel表和三次全员演练。增量迁移这门手艺,说到底是把“不可控”一点点变成“可控”的过程——先控住数据,再控住延迟,控住切换的每一个动作。数据库升级可以不中断,但前提是你得把每次增量同步都当成一次手术来做,术前有方案,术中有监控,术后有观察。技术工具年年更新,但这份敬畏心,什么时候都不能丢。


