十年前,我第一次参与数据库迁移的时候,整个人是懵的。凌晨两点,机房里空调嗡嗡作响,几十号人围着屏幕,等着割接窗口。那个晚上,我们用最笨的办法——把应用停机,把数据全量导出,再导入新库,然后改连接串,重启服务。整个过程持续了六个小时,期间业务完全不可用。好在是凌晨,用户没怎么察觉。但那会儿我就想,这种日子什么时候是个头。

停机割接的逻辑很简单,就是拿时间换确定性。数据库迁移最怕的是数据不一致,怕丢数据,怕两个库的序列号对不上。所以干脆停掉一切写入,让数据冻结在一个时间点,然后慢慢搬。这套思路在业务量小、系统不复杂的年代是够用的。毕竟那时候一套系统可能就服务几千个用户,半夜停机几个小时,影响面有限。而且运维团队也习惯了这种节奏,把所有风险都摊在一个可控的时间窗口里。
但事情在变。现在的系统,哪怕是一个中等规模的电商平台,用户量也是千万级起步。凌晨两点的流量低峰,对很多全球化业务来说根本不存在——你的凌晨是别人的下午。而且业务方越来越不能接受停机,哪怕是一分钟,都意味着真金白银的损失。我记得有一次做支付系统的迁移,业务方直接说,你们可以停机,但每停一分钟,财务那边就会收到一堆投诉工单。那种压力,不是技术能解决的。
所以迁移方案开始进化,第一步是缩短停机时间。既然全量导出导入太慢,那就先做全量复制,再做增量同步。思路是,在正式切换之前,让新旧两个库并行跑一段时间,新库实时接收旧库的变化。这样到了切换那一刻,其实只需要把增量补上,然后改一下连接串,停机时间就能压缩到几分钟。这个方案在当时已经算先进了,但本质上还是割接,只是把窗口缩小了。
再往后,有人开始碰真正的平滑切换。核心思路是让应用层感知不到数据库的变化。怎么做?中间加一层代理,或者用读写分离的思路。写操作走主库,读操作走从库,迁移的时候,把新库伪装成旧库的从库,持续同步数据。等数据追平了,就把流量一点点切过去,先切读流量,再切写流量。整个过程业务无感,甚至可以在白天操作。这个方案的技术难点不在数据复制,而在流量调度和一致性保障。
不过,平滑切换听着美好,落地全是坑。我见过一个团队做平滑切换,读流量切过去了,但有个报表查询特别慢,直接把新库的CPU打满,连带着影响了已经切过去的业务。后来查了半天,发现是索引没建全。这种问题是停机割接不会遇到的——因为停机割接有大把时间做检查和验证,而平滑切换要求你在流量实时变化的情况下,保证新旧两套系统的性能表现一致。说白了,停机割接是考试,平滑切换是实战。
现在做得比较成熟的方案,是数据同步工具加流量调度平台的组合。数据同步负责把变更实时搬到新库,流量调度负责灰度切流。灰度切流可以做到百分之一、百分之五、百分之十这样逐步递增,每切一步就观察一段时间,发现异常就回滚。这个机制很重要,因为数据库迁移最怕的就是一刀切,切过去发现问题想回来就难了。灰度切流给了你试错的余量,也让团队心里有底。
但工具再成熟,也替代不了人的判断。我始终觉得,数据库迁移这件事,七分靠工具,三分靠经验。工具能帮你处理数据的搬运,但判断什么时候切、切多少、观察多久,这些决策需要人对业务的理解。比如有些业务对数据延迟极其敏感,同步延迟超过一秒就会出问题,这种场景下工具再快也白搭,你得提前跟业务方对齐容忍度,甚至专门为这个业务设计特殊路径。
回到标题那句话,“从停机割接到平滑切换”,这八个字背后是整整一代运维人的成长史。停机割接不是错的,它是在那个技术条件下最稳妥的选择。平滑切换也不是万能的,它引入的复杂度可能比它解决的问题还多。但方向是明确的:业务不能停,数据不能乱,迁移要像换轮胎一样——车还在跑,轮胎已经换好了。这条路还没走完,未来还会有更聪明的方案,但核心逻辑不会变:让用户在无感知的情况下,完成系统的迭代。


