数据迁移基础

数据迁移,说白了就是把数据从一个地方搬到另一个地方。

听起来简单吧?但真正做过的人都知道,这里面坑不少。我刚开始做第一个迁移项目时,以为就是个复制粘贴的活儿,结果线上跑了三天三夜,最后发现校验对不上——那叫一个头大。

所以这一节,咱们先打好基础。把概念、类型、流程理清楚,后面再聊校验就顺了。

什么是数据迁移?

数据迁移是指将数据从源系统(或存储)整体或部分地转移到目标系统的过程。目标系统可能是新数据库、新文件系统、新云服务,甚至只是换个版本。

我个人的习惯是,把迁移分成两类情况:

  • 同构迁移:源和目标类型一样,比如 MySQL 5.7 → MySQL 8.0。
  • 异构迁移:类型不同,比如 Oracle → PostgreSQL。这种挑战更大,因为数据类型、约束、索引都得重新映射。
一个小技巧:不管同构还是异构,先在预发环境跑一次完整迁移。我曾经跳过这一步,结果生产上遇到字符集乱码,回滚花了整晚。

两种核心迁移类型:全量 vs 增量

这就取决于你能停多长时间的业务了。咱们来对比一下。

维度 全量迁移 增量迁移
数据范围 一次性迁移所有数据 只迁移变化的数据(新增/修改/删除)
执行时间 取决于数据总量,通常较长 轻量,可持续运行
业务停机 一般需要业务窗口 可做到近乎零停机
一致性校验 迁移后整体校验一次 需要持续校验,保证增量不丢失
常见场景 初次上云、版本大升级 实时同步、灾备

我见过很多团队一上来就想做增量迁移,觉得不停机很酷。但你没想清楚,增量迁移的前提是全量基准必须正确。否则增量数据叠在错误的基础上,后面校验永远对不上。

核心原则:全量打底,增量补漏。 先跑一次全量,校验通过再开增量通道。

迁移流程长什么样?

这里我总结一个通用流程,后面每一章都会回头参考它。

  1. 评估与规划:梳理源数据结构、数据量、表关系、业务停机容忍度。
  2. 全量导出:从源系统导出完整数据集,尽量保证导出时数据一致(比如用快照或读锁)。
  3. 全量导入:把数据写入目标系统,注意字段映射、类型转换、索引重建。
  4. 全量校验:对比源和目标的行数、散列值或关键字段,确保无遗漏。
  5. 增量捕获:开启变更数据捕获(CDC)或日志解析,记录全量导出后的所有变更。
  6. 增量同步:将变更持续应用到目标系统,顺序不能乱。
  7. 增量校验:周期性或按事件触发,校验增量部分是否完整一致。
  8. 切换与收尾:验证无误后,切换读写流量到目标,清理临时数据。

你想想看,这八步里,校验步骤出现了两次(全量校验和增量校验)。为什么?因为迁移最怕的就是:数据丢了、多了、错了,而你自己不知道。

我曾经踩过的坑:有一次做全量迁移,我把校验只放在最后一步,结果中途网络闪断导致某张表只导入了80%的数据,直到业务报错才发现。从那以后,我每张表导入完都立刻做一次简单校验(至少对比行数和主键最大值)。

一个简单的代码思路

这里不贴完整代码,给你一个校验行数的伪代码片段。你感受一下。

def full_validate(source_conn, target_conn, tables):
    for table in tables:
        src_count = source_conn.query(f"SELECT COUNT(*) FROM {table}")
        tgt_count = target_conn.query(f"SELECT COUNT(*) FROM {table}")
        if src_count != tgt_count:
            raise Exception(f"表 {table} 行数不一致: 源 {src_count} 目标 {tgt_count}")
    print("全量校验通过")

这行代码简单吧?但实际项目里我见过好多团队连这个都不写,就敢上线。

本章核心逻辑图

下面这张图把全量、增量和校验的关系画在一起,你一看就明白。

数据迁移核心流程框架 源系统 目标系统 全量导出 全量导入 全量校验 增量捕获 增量同步 增量校验 全量校验通过 → 开启增量通道 → 持续增量校验 任何一步校验失败,立即暂停并回滚