做数据集成时,很多人都会碰到三个词: 全量同步、增量同步、CDC。 表面上看并不复杂。 全量,就是把全部数据重新同步一遍; 增量,就是只同步新增或变化的数据; CDC,好像也是只处理变化的数据。 于是问题就来了: 既然已经有增量同步了,为什么还要 CDC? 甚至很多项目里,会直接把"增量同步"和"CDC"当成一回事。 其实这三个概念并不完全处在同一个维度。 全量和增量主要回答的是:这次到底同步哪些数据。 CDC 回答的则是: 数据库发生变化以后,系统怎么知道"哪里变了"。 看起来只是一个小区别,但把它搞清楚以后,很多实时数仓、数据迁移、数据集成里的问题就会一下子顺起来。
一、全量、增量、CDC,其实不是三个并列选项 假设业务系统里有一张订单表,目前有 1000 万条数据,需要同步到数据仓库。 最简单的方法就是: 1000 万条全部读取,再全部写过去。 这就是全量同步。 第二天又新增了 10 万条订单。 如果再把 1010 万条重新同步一遍,当然也可以。 但问题是: 其中 1000 万条根本没有变化。 于是就有了增量同步: 只处理相对上一次新增或发生变化的数据。 所以全量和增量,首先描述的是处理范围。 全量关心的是: 整个数据集。 增量关心的是: 变化的数据集。 但"只同步变化的数据"还有一个前提: 你得先知道哪些数据发生了变化。 怎么判断? 可以看更新时间,可以看自增 ID,可以做前后数据比对,也可以直接读取数据库产生的变化日志。 CDC 就是最后这一类思路。 因此,更准确的关系其实是: 全量和增量决定"同步多少",CDC 解决"变化怎么被发现"。 也正因为如此,真实项目里通常不会要求所有数据走同一种模式。 配置表可能每天全量一次; 销售明细可能按照更新时间增量抽取; 订单、库存、支付这类高频变化的数据,再单独考虑 CDC。 真正落到项目里,很少会让所有表采用同一种同步方式。配置表、字典表的数据量不大,可以定时全量覆盖;销售明细有稳定的更新时间字段,可以做周期增量;订单、库存、支付这类持续发生变化的数据,再根据时效要求考虑 CDC。 实际用 FineDataLink 5.0 搭这类链路时,可以先按照数据量、变化频率、同步周期和业务重要程度把表分组,再分别设计对应的同步方式,后续的数据处理和目标端写入也跟着各自的链路走。 这样做的好处是,技术方案不会被"一刀切"。全量、普通增量和 CDC 本来就应该长期共存,而不是互相替代。
二、全量同步并不落后,关键是看成本 很多人一听"全量同步",就觉得这种方式比较原始。 其实不一定。 假设一张地区编码表只有 5000 行,一个月可能才调整几次。 每天凌晨全部覆盖一遍,可能几秒钟就结束。 这种情况下,专门设计复杂的增量逻辑,反而会增加维护成本。 所以全量同步更适合: 数据量小、变化频率低、时效要求不高的数据。 比如: 组织架构、地区编码、基础配置、商品分类和部分维度表。 真正的问题通常出现在数据规模不断增长以后。 假设一张交易表已经有 20 亿条记录,每天真正发生变化的只有 500 万条。 如果为了得到这 500 万条变化,每天还要重新读取 20 亿条,会逐渐出现三个问题。 第一,业务库压力越来越大 全表扫描会持续消耗数据库 CPU、IO 和网络资源。 数据仓库自己跑得慢是一回事,如果同步任务反过来影响生产系统,那问题就严重了。 第二,同步窗口越来越长 以前凌晨 1 点开始,2 点跑完。 数据越来越多以后,可能到 5 点还没有结束。 最终就会出现: 上一批数据还没有跑完,下一批任务又开始了。 第三,数据时效越来越差 业务上午看到的所谓"最新数据",实际上可能仍然是昨天晚上的状态。 所以判断是否应该从全量切换到增量,本质上是在算一笔账: 扫描全部数据的成本,是否已经明显高于识别变化数据的成本。 如果答案是肯定的,就应该开始考虑增量。
三、增量同步真正难的,不是"只同步新增" 最常见的增量方案,是使用更新时间字段。 例如订单表里有: update_time 上一次任务同步到: 2026-09-01 00:00:00 那么下一次只读取: update_time > 上次同步时间 看上去非常简单。 如果数据只会新增,还可以直接按照自增 ID 处理。 例如: 上一次同步到 ID=100000, 下一次只查: ID > 100000 但真实业务数据很少只会新增。 一笔订单可能经历: 创建 → 支付 → 发货 → 完成 → 退款。 这里面大量变化都是 Update。 更麻烦的是 Delete。 如果源库已经把一条记录删除,那么下一次再查更新时间时,这条记录根本不存在。 目标库怎么知道: 这条数据也应该删掉? 所以真正的增量同步至少要回答四个问题: 新增怎么发现? 修改怎么发现? 删除怎么发现? 上一次到底同步到了哪里? 这也是为什么"增量同步"并不是一种固定技术。 它背后可能是: 主键增量、时间戳增量、状态字段增量、数据比对,甚至 CDC。 如果一张销售明细表只要求每小时刷新一次,而且更新时间字段可靠,那么普通增量完全够用。 真正做任务时,反而要把几个细节提前想清楚: 增量边界取哪个字段? 相同业务主键再次出现时怎么处理? 目标端是追加、更新还是覆盖? 任务失败以后,下次从哪里继续? 所以很多小时级、天级的数据同步,其实普通增量已经够用了。 真正设计任务时,最好把增量条件和目标端更新规则放在一起考虑。比如同一个订单第二次被抽取出来,是直接覆盖整行,还是只更新发生变化的字段?如果目标表已经存在这条记录,又应该按哪个业务主键进行匹配? 在 FineDataLink 5.0 里做这类任务时,增量判断、字段映射、过滤转换和目标端写入可以放在同一条处理流程里配置。这样后面业务字段或者同步规则发生调整时,也能从整条任务去检查,而不是只改一个抽数条件。 普通增量真正的边界,往往出现在删除难以识别、修改过于频繁,或者轮询源表的成本越来越高之后。到了这一步,再引入 CDC 才有意义。
四、CDC 到底是什么?核心不是"增量",而是"变化事件" CDC,全称: Change Data Capture,变化数据捕获。 理解 CDC 最关键的一点,是不要把它简单理解成: 一种更快的增量同步。 传统增量查询更像是在问: 从我上次来过以后,现在有哪些数据和以前不一样? 而 CDC 关注的是: 数据库刚刚发生了什么变化? 例如一笔订单金额原来是 100 元,后来改成 120 元。 如果现在查询订单表,只能看到: 120 元。 但 CDC 关注的是: 这条记录从 100 变成了 120。 前者看到的是: 当前状态。 后者记录的是: 变化过程。 这就是 Snapshot 和 Change Event 之间很重要的区别。 很多数据库为了事务恢复、主从复制,本身就需要记录数据变化。 例如: MySQL 有 Binlog, PostgreSQL 有 WAL, Oracle 也有自己的日志机制。 CDC 做的,就是从这些变化记录里把 Insert、Update、Delete 识别出来,再继续交给下游处理。 所以一条完整的 CDC 链路可以理解成: 业务数据库 → 变化日志 → CDC 捕获 → 数据处理 → 数仓 / 湖仓 / 消息系统 / 业务系统 这里还有一个很容易被忽略的问题: 捕获到变化,并不代表数据已经能用了。 日志里的字段可能还需要清洗; 不同系统的编码可能需要转换; 部分字段可能需要过滤; 最终还要决定写进哪张目标表。 这也是为什么判断一套 CDC 方案,不能只看它能不能读 Binlog。 捕获出来的 Insert、Update、Delete 还只是变化事件。进入下游之前,往往还要经过字段筛选、格式转换、数据清洗,甚至重新匹配业务主键,最后才能写入数仓、消息系统或者其他业务库。 FineDataLink 5.0 在这一段链路里承接的就是后续处理:前面拿到数据库变化,后面继续完成转换、过滤和目标端写入。CDC 也因此不再是一个孤立的"日志采集动作",而是整个数据集成流程中的一环。 变化捕获只是起点,把变化加工成下游真正能消费的数据,才算把这条链路做完整。
五、CDC 为什么不等于实时同步? 这是一个特别容易混淆的问题。 很多人默认: 用了 CDC = 实时同步。 其实不准确。 CDC 解决的是: 变化怎么被发现。 实时同步解决的是: 变化多快到达下游。 假设订单在 10:00:00 发生变化, 10:00:01 已经被 CDC 捕获, 但是数据进入消息队列以后,每 10 分钟才统一处理一次。 那么它虽然使用了 CDC,最终业务看到的数据仍然可能延迟 10 分钟。 反过来,一套设备系统每 3 秒主动推送一次状态数据,也可能非常实时,却根本没有数据库 CDC。 所以真正的实时链路应该拆成: 变化产生 → 变化捕获 → 数据传输 → 数据处理 → 目标端写入 → 下游消费 任何一环发生积压,最终数据都会延迟。 例如: 数据库 10:00:00 产生订单, 10:00:01 被捕获, 10:00:02 进入消息系统, 10:03:00 才写进数仓。 那么真正的业务延迟不是 1 秒,而是: 3 分钟。 所以企业判断一条链路是否"实时",真正应该关注的是: 端到端延迟。 而不是只看 CDC 这一环有多快。
六、真正做 CDC,最难的是"不丢、不重、不乱" CDC 概念本身并不复杂。 真正难的是: 跑进生产环境以后还能不能长期稳定。 任务挂了以后,从哪里继续? 假设凌晨 2 点任务突然中断。 2 点 05 分恢复。 系统不能简单从"当前最新位置"开始。 否则中间 5 分钟产生的数据可能全部漏掉。 所以 CDC 需要记录: 上一次已经确认消费到了哪里。 任务恢复以后,再从正确的位置继续。 重复数据怎么办? 网络异常、任务重试,都可能让同一条变化被处理两次。 因此目标端必须考虑: 幂等。 同一个订单事件即使重复执行,最终结果也不能被写乱。 顺序乱了怎么办? 订单原本按照: 创建 → 支付 → 退款 发生。 如果下游最后按照: 创建 → 退款 → 支付 处理,最终状态就可能错误。 所以 CDC 不仅要关心吞吐量,还必须关心: 事件顺序和事务顺序。 表结构变化怎么办? 今天新增字段, 明天字段类型变化, 后天业务系统又重构了一张表。 这些 Schema Change 都会沿着链路影响下游。 所以 CDC 上线一段时间以后,真正让人头疼的问题往往会从: "数据能不能同步过去?" 变成: "为什么这张表突然延迟了?" "任务失败以后从哪里恢复?" "哪个字段变化把下游任务打挂了?" 当企业只同步十几张表时,这些问题靠人工还能处理。 但 ERP、CRM、MES、WMS 都接进来以后,几十条甚至几百条任务散落在脚本、服务器和定时器里,维护难度会迅速上升。 当同步规模扩展到几十张、几百张表以后,问题会明显从"怎么开发"转向"怎么维护"。 ERP、CRM、MES、WMS 里的任务同时运行,任何一个环节出现异常,都可能带来延迟、积压或者数据缺失。这个阶段再看 FineDataLink 5.0,价值就不只是把任务跑起来,而是让原本散落在脚本、定时器和不同服务器上的同步链路有统一的任务环境。出现问题时,可以先判断是哪条任务、哪个处理环节发生异常,再针对性排查。 所以 CDC 做到后面,考验的其实已经不是一次性的开发能力,而是长期运行、故障恢复和维护成本。链路越多,这部分的重要性越高。
七、全量、增量、CDC,到底应该怎么选? 最后给一个比较实用的判断框架。 第一类:小表、低频变化 比如: 地区、组织、基础配置。 直接: 定时全量。 不要把简单的问题复杂化。 第二类:数据量较大,但时效要求一般 比如小时级、天级经营数据。 如果更新时间字段可靠,可以用: 时间戳增量。 如果只新增,也可以用: 主键增量。 第三类:数据量大,而且频繁增删改 例如: 订单、支付、库存、物流、交易流水。 同时业务又要求分钟级甚至秒级更新。 这时候才真正进入 CDC 比较典型的场景。 第四类:第一次建设 CDC 链路 通常也不是直接打开 CDC 就结束。 因为目标端一开始还是空的。 所以更常见的模式是: 全量初始化 + CDC 持续增量。 先把历史数据形成完整基线,再从一个准确的位置继续接后面的变化。 这背后其实就是一个很经典的思路: Snapshot + Change Stream 也就是: 存量快照 + 持续变化流。
写在最后 所以以后再看到: 全量同步、增量同步、CDC 不要把它们理解成三种从低到高的技术。 它们解决的问题本来就不完全一样。 全量同步解决的是: 现有数据怎么完整搬过去。 增量同步解决的是: 后续怎么只处理变化部分。 CDC 解决的是: 这些变化到底怎么被及时、准确地发现。 真正成熟的数据同步架构,也往往不是只有一种方式。 而是: 小表定时全量,大表周期增量,核心高频业务表再做 CDC。 做技术选型时,也不要先问: "CDC 是不是比普通增量高级?" 而应该先回答: 数据量有多大? 变化有多频繁? 有没有 Update 和 Delete? 允许多大延迟? 源数据库能承受多少查询压力? 任务失败以后怎么恢复? 重复、乱序和表结构变化怎么处理? 这些问题想明白以后,到底该用全量、增量还是 CDC,其实并不难选。 数据集成真正成熟的标志,从来不是: 所有数据都实时。 而是能够根据不同数据的规模、变化频率、业务价值和时效要求,选择一条成本、复杂度和可靠性真正匹配的同步链路。