数据迁移是一条单独的赛道
一句话总结
数据迁移不是开发结束后才开始的工作,而是一个与开发并行推进的独立轨道;迁移中发现的数据问题甚至可能改变设计。
为什么这是个问题
把迁移推迟到项目后期,会让问题暴露得太晚。而迁移中出现的问题,往往都是可选方案取决于剩余时间的问题。
假设新 schema 中某列被定义为 NOT NULL,但遗留系统中有 30% 的值为空。提前 6 个月知道,就能修改 schema、商定默认值规则,或要求业务部门整理数据;上线前 2 周才知道,通常只剩一个选择——随便填一个值进去。 而这个填进去的值会在系统中留存多年。
迁移不是项目后期的工作
新一代系统项目复盘中,有一条反复出现的教训。
数据迁移必须从项目初期起作为独立轨道管理。
原因很简单。迁移不是必须等开发完成才能开始的工作, 而是应与开发并行推进的工作。 而且迁移过程中发现的数据问题,也可能反过来改变设计。
现场经常发生这些情况:
- 新 schema 中定义为
NOT NULL的列,在遗留系统中有 30% 是空值 - 发现 47 个无法映射到新代码体系的遗留代码值
- 遗留系统中同一客户仅因姓名写法不同就存在 3 条记录
上线前两周才发现这些问题,就几乎没有选择;提前六个月知道,则可以修改 schema、商定清洗规则,或请求业务部门整理。
迁移演练要做三次
大型项目的迁移计划通常包含多次演练。
1차 리허설 (D-90) : 절차 확인. 시간이 얼마나 걸리는가
2차 리허설 (D-30) : 데이터 품질 확인. 정제 규칙 검증
3차 리허설 (D-7) : 실전과 동일 조건. 시간·순서·인원 확정
演练真正的产出不是数据,而是实际耗时测量值。只有能用测量而不是估算说明“迁移需要 4 小时”,迁移计划的时间线才成立。而多数项目在第一次演练时都会发现,实际耗时是预估的 2~3 倍。
AS-IS → TO-BE 映射定义书
这是迁移最核心的产出物,应按列记录如下。
| TO-BE 表 | 列 | AS-IS 来源 | 转换规则 | 无法映射时 |
|---|---|---|---|---|
| CUSTOMER | CUST_NM | TB_CUST.NAME | TRIM,空白规范化 |
报错 |
| CUSTOMER | REG_DT | TB_CUST.REGDATE | YY/MM/DD → YYYYMMDD |
19000101 |
| CUSTOMER | GRADE_CD | TB_CUST.LEVEL | 参照代码映射表 | 99(其他) |
| ORDERS | ORD_STS_CD | TB_ORD.STATUS | 参照代码映射表 | 排除迁移 |
其中最关键的是“无法映射时”这一列。遇到无法映射的值,究竟应报错、填默认值,还是排除整行,必须提前决定。否则开发人员会自行处理,最终只留下“记录数对不上”的结果。
而且,被排除的记录必须保留清单。 “1,200 条中迁移 1,187 条、排除 13 条”才是完整结果,并且必须能够回答那 13 条究竟是什么。
数据清洗实际做什么
遗留数据通常长这样。
| 症状 | 示例 | 处理 |
|---|---|---|
| 首尾空格 | " 홍길동 " |
TRIM |
| 日期格式混杂 | 20260801、2026-08-01、26/08/01 |
统一格式 |
| 字符串 NULL | 值是字符串 "NULL" 或 "null" |
转为真正的 NULL |
| 金额带格式 | "1,250,000" |
去掉逗号并转为数值 |
| 重复 | 同一键有多条记录 | 按规则只保留一条(通常取最新修改日) |
| 代码值不一致 | 已废弃代码、拼写错误 | 映射表或其他代码 |
| 编码损坏 | ????? |
从源系统重新抽取 |
去重规则必须与业务方协商。“保留最新记录”看似自然,但最新记录也可能反而不完整。这不是技术判断,而是业务判断。
验证——分四层进行
迁移后的验证应从下到上逐层进行,缺少任何一层都会留下漏洞。
1. 스키마 검증 테이블·컬럼·타입·제약·인덱스가 의도대로 있는가
2. 데이터 검증 건수 · 합계 · NULL 개수 · 체크섬
3. 성능 검증 주요 쿼리의 실행계획과 응답시간
4. 애플리케이션 핵심 업무 시나리오 스모크 테스트
需要再次强调第 2 层为什么要使用校验和。仅比较记录数和合计值,无法发现“少了一条、另一条又翻倍”的情况;比较排序后键列表的哈希,才能发现这种问题。
-- 개념적으로: 키를 정렬해 이어 붙인 문자열의 해시
SELECT md5(group_concat(CUST_ID, ',' ORDER BY CUST_ID)) FROM CUSTOMER;
不同验证方式的成本与可信度如下。
| 方法 | 成本 | 可信度 |
|---|---|---|
| 抽样检查 | 低 | 低~中 |
| 汇总(记录数、合计) | 低 | 中上 |
| 校验和 | 中 | 高 |
| 全量比对 | 高 | 极高(金融等必须保证完整性的领域) |
迁移结果确认书
不能只做口头确认,必须留下文档。
## 이관 대상
CUSTOMER 원천 1,200건 → 이관 1,187건, 제외 13건
ORDERS 원천 45,320건 → 이관 45,320건, 제외 0건
## 제외 사유
코드 미매핑 9건 (목록: excluded_code.csv)
필수값 누락 4건 (목록: excluded_null.csv)
## 검증 결과
건수 일치 OK
금액 합계 일치 OK (원천 8,213,400,000 / 대상 8,213,400,000)
키 체크섬 일치 OK
## 재이관 대상
13건 - 업무 정리 후 D+3 재이관 예정, 담당 ○○○
## 확인
수행사 ___ 발주사 ___
有了这份文档,上线后收到“数据怎么不见了”的询问时,就能回答:这 13 条属于迁移排除对象,计划在 D+3 重新迁移。 没有文档,就只能从头调查。
迁移失败时的原则
最后还有一项原则,适用于迁移过程中出现问题时。
修改数据的恢复方式只能作为最后手段。
顺序如下。
- 尽可能用功能开关关闭新路径
- 把流量切回旧系统
- 仍无法解决时,再回滚 schema
- 最后才恢复数据(从备份恢复或按时间点恢复)
第 4 步耗时最长、风险最高。因此,预先准备好前三步,才真正体现迁移计划的质量。
在实际项目中
判断迁移是否完成时,标准也经常错位。“没有报错地跑完了”并不等于完成。做对账后,经常发现记录数或金额合计不一致,真正的标准是:这种差异能否解释。
如果因为去重而减少 20 条,记录数当然不会一致,但这是正常差异;反过来,如果毫无理由地少了 3 条,那就是事故。因此,对账表不应只有把差异归零的栏位,还必须有记录差异及其原因的栏位。
被排除记录的清单也必须保留。没有这个文件,上线后面对“我们的客户数据没迁过来”的询问就无从回答,而届时再重新统计已经不可能。