数据库迁移这事儿,干过的人都懂,表面上一行“ALTER TABLE”搞定,背后却藏着无数坑。MySQL作为最流行的开源关系型数据库,几乎每个互联网公司都会遇到迁移需求——业务扩张要换机型、机房搬迁要换地儿、版本升级要换特性。可问题来了,迁移过程中数据库不能停,一停就是真金白银的损失。电商大促期间宕机一分钟,GMV少说六位数;社交平台数据库挂了,用户直接骂到热搜。所以“零停机”这三个字,不是锦上添花,而是生死线。

很多新手上来就想着“导出导入”,用mysqldump吭哧吭哧跑一遍,数据量小还行,一旦上了几百GB,那简直是自掘坟墓。你正导着数据,业务还在写入新数据,两边一冲突,不是数据不一致就是锁表死掉。更惨的是,导出过程中网络断了,一切白干,还得重来。真正靠谱的迁移方案,核心原则只有一个:先同步,再切换。你得让新库和旧库的数据保持一致,然后找个没人注意的窗口期,瞬间切过去。这个“瞬间”最好是秒级,最多不超过分钟级,用户完全感知不到。
具体怎么操作?第一步是评估数据量和业务场景。你手里是MySQL 5.7还是8.0?表结构有没有大字段、有没有分库分表?数据量是10GB还是10TB?这些直接决定工具选型。小数据量用mysqldump加--single-transaction参数,可以做到一致性快照导出,但前提是引擎是InnoDB,MyISAM就别想了,它不支持事务,导数据时必须锁表。大数据量得用物理备份工具,比如Percona XtraBackup,它直接拷贝数据文件,速度快得多,还能做到热备份。不过XtraBackup对版本要求严格,MySQL 8.0以上得用对应版本,否则拷贝出来的文件没法直接恢复。
第二步是搭建同步链路。这一步最考验技术深度。很多人以为导出导入完就结束了,其实不然。你得让新库实时同步旧库的变更,才能实现零停机。MySQL内置的同步机制是主从复制(Replication),但传统的主从复制有个致命缺陷——它基于二进制日志(binlog),而binlog的行模式(ROW)会记录每条变更的完整数据。如果你旧库写量大,新库的SQL线程可能追不上,延迟越拉越大,最终切换时数据不一致。这时候就得考虑第三方工具,比如阿里巴巴开源的Canal,或者谷歌的gh-ost。Canal伪装成MySQL的从库,解析binlog后把变更发给新库,延迟控制在毫秒级。gh-ost则更暴力,它直接在旧库上创建触发器,把数据写入新库,但触发器有性能损耗,高并发场景慎用。
第三步是数据校验。你以为同步链路搭好了就万事大吉?天真。binlog解析过程中,字段类型转换、字符集差异、自增主键冲突,任何一个小问题都能让你数据对不上。你得在切换前做一次全量校验,用工具如pt-table-checksum(Percona Toolkit里的神器)对比旧库和新库的每个表、每条记录。它会计算每行数据的校验和,然后比对两边是否一致。不一致的记录下来,用pt-table-sync修复。这个过程很耗时,10TB数据跑校验可能要十几个小时,但必须做。我见过最惨的案例,某公司迁移后一个月才发现有个表少了三百万条记录,原因就是binlog里有个UNSIGNED INT字段溢出,MySQL自动截断了但没报错。
第四步是灰度切换。这一步最讲究策略。你不能直接一刀切,把所有流量都打到新库。万一新库性能不如预期,或者有隐藏bug,全站就崩了。正确的做法是:先用DNS解析或者负载均衡器,把1%的读流量切到新库,观察几分钟,看有没有错误日志、慢查询、连接超时。没问题了,再逐步扩大到10%、50%,100%。写流量更谨慎,得在确认新库完全同步旧库后,停掉旧库的写操作,然后把写流量切过去。这个停写窗口越短越好,最好控制在30秒内。怎么做到?在业务低峰期,比如凌晨三点,先暂停所有应用服务的写操作,等旧库的binlog完全被新库消费完,再切换DNS,恢复写操作。整个过程自动化脚本跑,人工只需点确认按钮。
第五步是回滚预案。这是一道防线,但很多人懒得做。你得准备好回滚脚本,一旦新库出问题,能在五分钟内切回旧库。回滚不是简单地把DNS改回去就完事,因为旧库在迁移过程中可能已经有一些新数据写入,这些数据得反向同步回旧库。所以你在搭建同步链路时,最好双向同步,或者至少保留旧库的binlog一段时间。如果新库出的是硬件故障,比如磁盘坏了,那回滚更麻烦,得从备份恢复。所以迁移前一定要做全量备份,并存放在不同机房。
说到这里,你可能会觉得迁移好复杂,但其实核心逻辑就一条:通过冗余和监控,把风险降到最低。我见过最牛的团队,他们用一套自动化平台,一键触发迁移,从数据同步、校验、灰度切流到回滚,全流程走完只要两小时。背后的原理并不神秘,就是把上述步骤拆解成模块,每个模块都加上熔断机制——比如校验发现数据不一致超过0.1%,自动停止切换并报警。这样就算遇到突发问题,也能快速定位。
说个容易被忽视的细节:迁移完成后,旧库别急着删。很多公司为了省成本,迁移完第二天就把旧库服务器回收了。结果第三天发现新库有个索引建错了,业务查询慢成狗,想回滚发现旧库没了,只能从头再来。正确的做法是保留旧库至少一周,期间每天跑一次数据对比,确保新库运行稳定。等业务验证通过后,再慢慢把旧库下线。这个“慢慢”也很重要,下线前要先停掉旧库的读写,观察几天看有没有业务依赖报错,确认没问题了再销毁。毕竟,数据库迁移不是一锤子买卖,而是一次对技术体系的全方位体检。


