数据迁移与 CDC
凌晨两点,迁移控制台显示“全量完成、增量延迟 0 秒”,业务切到新库后却发现昨天删除的订单重新出现,少量用户余额停在旧版本。团队随后才确认:全量任务读取的是一个时间点,CDC 从另一个日志位置启动;行数对得上,但删除事件没有进入目标,更新乱序又让旧值覆盖了新值。任务成功只证明工具没有继续报错,不能证明目标库已经成为可信事实。
可靠迁移必须同时回答五个问题:全量基线代表哪个一致性时间点,增量从哪个可恢复位点继续,重复和乱序怎样在目标收敛,源目标用什么证据证明等价,业务在什么条件下切换写入并保留回切能力。任何一个答案含糊,迁移就只是规模更大的复制脚本。
先辨认迁移正在改变什么
停机搬迁适合数据量可控、业务允许冻结写入的系统:停止写入,导出一致性快照,导入目标,校验后一次切换。它的链路短,却必须把停机时间拆成导出、传输、导入、索引构建、校验和应用验证,不能用一次测试环境耗时承诺生产窗口。
在线迁移先建立全量基线,再用数据库日志持续捕获增量,待目标追平后短暂冻结或受控双写,完成最终校验和切流。它减少停机,却引入位点、日志保留、重复、乱序、Schema 演进、目标幂等和回切同步等状态。CDC 用于搜索投影、数据平台或事件流时可能长期运行;用于一次性搬迁时则必须设计停止点和清理,不让临时链路变成永久无人维护的生产依赖。
图中的水位不能只是一串工具内部 offset。它还要能映射到数据库提交顺序、目标已应用版本和业务可见状态。Kafka 中已有事件不等于目标库已写入,目标写入成功也不等于缓存、搜索和应用连接已经切换。
从现场约束选择工具
MySQL 跨环境或跨版本逻辑搬迁,先看 MySQL 逻辑迁移。小库可使用 mysqldump 获得可审查 SQL,大库更关注 MySQL Shell 并行 Dump/Load、对象兼容、字符集、账号与 GTID;物理备份和 PITR 继续由数据库与运维手册负责。
PostgreSQL 的 custom/directory dump、并行恢复、global objects、owner、extension、序列和 collation 在 PostgreSQL 逻辑迁移 中形成独立链路。pg_dump 能跨 major 做逻辑迁移,不代表目标 extension、locale、权限与执行计划自然等价。
需要长期运行 connector 时,先建立 Kafka Connect 运行时 的 worker、插件、内部 topic、REST、授权和恢复事实,再接入 Debezium MySQL 或 Debezium PostgreSQL。把 Debezium JAR 放进容器只完成了安装;snapshot、schema history、offset、GTID/LSN、日志保留与下游幂等共同决定能否恢复。
需要用声明式 Pipeline 把多类 source 送入分析或湖仓 sink,并依赖 checkpoint/savepoint 管理作业状态时,进入 Flink CDC。它建立在 Flink 作业运行模型上,适合团队已经能治理 JobManager、TaskManager、checkpoint 存储和 connector 兼容的场景,不是更轻量的 Debezium 替代品。
MySQL 单源轻量 binlog 捕获可分别评估 Canal 与 Maxwell。两者必须独立判断维护状态、输出协议、schema/position 存储、bootstrap、单点和目标 producer 失败;“部署简单”不等于可以忽略位点备份与断档恢复。
云上迁移分别查看 阿里云 DTS 与 AWS Database Migration Service。托管控制面减少自建 connector 运维,却不会替团队解决 VPC/专线、源库权限、目标容量、数据类型兼容、失败对象、业务冻结、校验、回切和任务退出。DTS、AWS DMS 与阿里云 DMS 也不是同一个产品,不能因缩写接近而混用能力结论。
迁移结束的判据来自校验与切流
Snapshot、CDC 与切流 把迁移拆成基线、追平、冻结或双写、灰度读、灰度写、全量接管、回切观察和旧链路退出。每一步都要有进入条件、超时、失败状态、唯一权威侧和退出证据。没有反向同步的新库一旦接收独占写入,直接把应用切回旧库会丢掉窗口内的新事实;所谓“保留旧库回滚”可能只是保留了一份越来越旧的副本。
迁移校验与对账 不把总行数和随机抽样当作完成。可靠校验按稳定主键分块,比较存在性、版本、规范化摘要和业务不变量,单独处理删除、NULL、时区、浮点/decimal、LOB 与无主键表。差异修复使用幂等写和明确权威方向,修复后必须重跑受影响分块及跨表不变量,避免修复动作制造第二轮漂移。
至少一次是常态,不是缺陷豁免
CDC 链路常在“读取源日志后、持久化位点前”或“目标写成功后、确认消息前”崩溃,因此恢复后可能重复。正确设计不是祈祷工具永不在窗口内故障,而是让事件带稳定主键、源位点或业务版本,让目标写入可幂等,让旧版本不能覆盖新版本,并观测重复率与拒绝原因。
Kafka Connect source exactly-once、Kafka transaction、Flink checkpoint 或云服务的“一致性”选项都有具体边界。数据库提交、connector、Broker、sink 和业务副作用没有处在同一个可证明事务中时,不能把某一段的 exactly-once 扩大成端到端业务只执行一次。架构评审应画出每个确认点,并为每个间隙准备重复、丢失或未知结果的恢复路径。
源库容量和日志保留决定迁移窗口
全量扫描会竞争 buffer、IO、CPU、锁和网络出口,目标导入还会放大 WAL/binlog、索引构建、约束检查和磁盘临时空间。限流不能只设每秒行数;还要观察源库查询延迟、复制延迟、buffer 命中、磁盘队列、日志增长,目标写入延迟、失败重试与存储水位。超过预算时应暂停或降低并发,而不是让业务与迁移相互拖垮。
CDC 最长可恢复中断时间受 binlog/WAL 保留、replication slot、Kafka topic、offset、schema history、checkpoint 和目标去重记录的最短保留期限制。slot 长期不推进可能撑满源库磁盘;过早清理日志则让 connector 无法续接,只能重新做 snapshot。容量计划要把迁移峰值、故障修复时间和回切窗口一起计入。
凭证和数据副本都要有退出日期
迁移账号通常需要读取大量表、查看日志位点或创建 publication/slot,目标账号需要批量写入、建表或禁用约束。这些权限按 source、target、任务和环境拆分,使用短期凭证、TLS 与受控网络入口;连接串不进入仓库、命令历史、任务 JSON、截图或错误日志。差异报告、死信和采样数据也可能包含生产敏感字段,必须脱敏、限权并设置保留期。
任务结束按可恢复顺序退出:停止新切流变化,确认回切窗口关闭,记录最终水位和校验摘要,停止 connector/任务,观察没有新增积压,撤销源目标账号与网络入口,删除 replication slot/publication、内部 topic 或复制实例前先满足审计保留,再清理临时对象、日志副本和告警。最后复核账单、密钥使用和源库日志增长已经回到基线。
团队运行要保留同一份迁移事实
一次迁移至少有业务 Owner、源库 Owner、目标平台 Owner、迁移工具 Owner、验证负责人和切流决策人。任何人都可以提出暂停,但只有明确角色能改变权威侧或越过校验门槛。变更单保存源目标指纹、工具与配置摘要、snapshot 水位、当前 offset/LSN/GTID、Schema 版本、差异统计、例外审批、切流时间、回切期限和清理证据。
长期 CDC 还要定义 SLO:源提交到目标可见的延迟、最老未处理位点年龄、失败/重复/乱序率、schema 不兼容次数、死信年龄、源日志保留余量、目标拒绝率和校验漂移。指标必须能定位到 connector、表或分片,却不能把主键、账号和业务数据直接放进高基数标签。
当团队能够从任意一次故障回答“最后可信基线在哪里、最后持久位点在哪里、哪些写入可能重复、哪些数据尚未证明一致、谁决定暂停或切流、怎样恢复并撤销全部临时权限”,迁移工具才真正提高效率。否则,自动化只是更快地产生一份无法解释的数据副本。
