数据库同步踩坑:全量、增量字段、CDC 到底该怎么选
最近做一个同步任务,问题不是“工具能不能跑”,而是“用哪种同步模式更不容易出事”。
源库是业务库,目标库是报表库。有人想每天全量覆盖,有人想按 update_time 做增量,也有人觉得直接上 CDC 最省心。最后我发现,真正要先问的不是“哪个更高级”,而是这些问题:
- 目标库有没有历史数据?
- 删除事件要不要同步?
update_time是否一定可靠?- 源库日志和权限能不能准备好?
- 任务失败后怎么确认目标库没少数据?
这篇按踩坑思路整理一下。工具上我用 DataMover 做验证,它能可视化配置全量、增量字段和 CDC,比较方便对比。这里的 DataMover 不是主角,主角还是同步模式选错以后会出现的漏数、重复和覆盖风险。
先看结论
| 场景 | 推荐模式 | 风险点 |
|---|---|---|
| 初始化目标库 | 全量 | 目标表已有数据时防误覆盖 |
| 低频刷新报表或测试库 | 全量/定期覆盖 | 大表执行时间和目标端索引 |
| 追加型业务表 | 增量字段 | 增量字段是否稳定推进 |
| 更新旧数据也要同步 | 增量字段或 CDC | 更新时间字段是否可靠 |
| 删除事件必须同步 | CDC | 日志、权限、快照、位点 |
| 秒级延迟 | CDC | 源库和目标端压力 |
如果需要快速把这些模式跑起来对比,DataMover 是一个可视化的数据迁移同步工具,支持全量、增量字段和 CDC。Docker 环境下可以直接执行:
curl -fsSL https://down.datamover.cn/install.sh | bash安装包入口:https://datamover.cn/download.html
文档地址:https://datamover.cn/doc/
试过的几种思路
直接全量
全量最容易理解,也最容易验证。缺点是大表成本高,目标表策略要特别清楚。
如果目标表为空,全量很好用。如果目标表已有数据,就要明确是清空、追加、写临时表,还是写新表再切换。这个策略不写清楚,后面出了问题没人说得清。
按字段增量
增量字段配置轻,不依赖数据库日志。自增 ID、update_time、入库时间都可以作为候选字段。
但它只适合字段可靠的表。比如 update_time 被业务代码统一维护,更新旧数据时一定变化,这就可以考虑。如果历史数据会回填,或者手工 SQL 不维护更新时间,就要小心漏数。
CDC
CDC 能捕获 INSERT、UPDATE、DELETE,适合实时同步。但它需要源库日志、权限、位点和快照策略。
这里的坑是:很多人只看到“实时”,没看到“前置条件”。上线前才发现 binlog 没开、账号权限不够、目标表已有数据不知道怎么处理,就很被动。
DataMover 配置过程
我用 DataMover 做这类任务时,一般按这个顺序:
- 新建源端数据源,测试连接。
- 新建目标端数据源,确认写入权限。
- 新建任务。全量/增量字段选普通任务,CDC 选实时任务。
- 选择源表和目标表。
- 检查字段映射,重点看类型、长度、默认值、主键。
- 普通任务配置同步策略:全量、增量字段、调度方式、批大小。
- 实时任务确认是否执行快照。
- 启动任务后查看输入、输出、失败数和执行日志。
DataMover 文档在这里:https://datamover.cn/doc/
DataMover 执行监控里能看到任务输入、输出和失败数据,这些信息要和后面的 SQL 校验一起看。
踩坑记录
1. 有更新时间字段,不代表可以放心增量
我见过不少表都有 update_time,但并不是每次更新都会维护。批处理脚本、历史修复脚本、人工 SQL 都可能绕过应用层逻辑。
处理方式:上线前抽样检查最近更新记录,确认 update_time 是否真的变化。
2. 目标表已有数据时,快照策略很危险
CDC 任务如果执行初始快照,就要确认目标表是否会被清空或覆盖。这个问题必须在任务启动前确认。
处理方式:目标表先备份,明确覆盖、追加、写新表还是从当前位点开始。
3. 进度 100% 不代表数据一致
任务完成只能说明流程跑完,不代表目标端数据和源端完全一致。目标端约束、字段截断、写入失败都可能导致数据少。
处理方式:看错误数据和日志,再跑 SQL 校验。
4. 批大小不是越大越好
批大小太大可能让 Worker 内存压力变高,也可能让目标端写入变慢。
处理方式:先用默认值跑通,再根据目标库写入能力和机器配置调整。
上线检查清单
| 检查项 | 现场表现 | 处理方式 |
|---|---|---|
| 增量字段不可靠 | 增量同步漏历史回填数据 | 改用 CDC 或补回填同步 |
| 目标表已有数据 | 快照或清空导致数据被覆盖 | 先备份,明确写入策略 |
| 字段类型不匹配 | 写入失败、精度丢失 | 先小表试跑并检查映射 |
| 字符集/时区不一致 | 中文乱码、时间偏移 | 统一连接参数 |
| DDL 变更无流程 | 源端加字段后目标端写入失败 | 上线前约定 DDL 变更流程 |
| 只看进度 | 目标端实际少数据 | 增加 SQL 校验和错误数据检查 |
SQL 校验
-- 行数校验
SELECT COUNT(*) FROM source_table;
SELECT COUNT(*) FROM target_table;
-- 时间范围校验
SELECT MIN(update_time), MAX(update_time) FROM source_table;
SELECT MIN(update_time), MAX(update_time) FROM target_table;
-- 状态聚合校验
SELECT status, COUNT(*) FROM source_table GROUP BY status ORDER BY status;
SELECT status, COUNT(*) FROM target_table GROUP BY status ORDER BY status;
-- 抽样校验
SELECT * FROM source_table WHERE id IN (1, 100, 1000);
SELECT * FROM target_table WHERE id IN (1, 100, 1000);金额类表:
SELECT status, COUNT(*) AS cnt, SUM(amount) AS total_amount
FROM source_table
GROUP BY status
ORDER BY status;总结
我的选择顺序是:
- 要建立基线,先全量。
- 有可靠增量字段,可以用字段增量。
- 要同步删除、复杂更新或秒级延迟,再上 CDC。
DataMover 能把这些模式集中到 Web 界面里配置,适合少写脚本。官网在 https://datamover.cn ,安装入口是 https://datamover.cn/download.html 。但无论用什么工具,目标端校验都不能省。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。