同步工具卷全量装载,这次是真懂工程
Jync v1.4.0 把异构数据库实时同步的初始全量装载从一条流式查询,升级为 keyset 分块、每块提交加检查点断点续传,单列整数主键表还能表内并行。本文拆解这版改动背后的工程逻辑:为什么全量装载才是同步工具真正的生死线,以及断点续传、并行切片、增量游标之间的取舍。
同步工具好不好用,全量装载见真章。
Jync v1.4.0 发布了。这个异构数据库实时同步工具,这次把版本主题全部押在一件事上:初始全量装载的可靠性与吞吐。
听起来不像大新闻。但做过数据迁移的人都知道,全量装载才是同步工具的生死时刻,不是增量同步。增量同步搞的是持续在线的数据流动,出问题可以重放、可以补、可以追。全量装载不一样——它是冷启动的第一公里,是从零把一张几亿行的 Oracle 表搬进 PostgreSQL 或别的目标库。这条路上任何一个环节崩了,代价都是整表重来。
这就是 v1.4.0 要解决的问题。
📈 全量装载为什么这么脆
先还原一个真实场景。
凌晨两点,数据工程师小王盯着屏幕上的进度条。目标库是空的,源库是 Oracle,任务是把三千万行的核心业务表搬过去。同步工具开启了一条流式查询,整表拉取,一切正常。进度条走到 70%,网络抖动,连接断了。
小王重启任务。
工具从头开始,重新拉。3000 万行,从第一行开始。
这不是段子,这是过去很多同步工具面对全量装载的真实行为。一条流式查询把整张表当成一个整体,没有任何中间状态,崩溃即归零。表小无所谓,表一大,这个设计就是定时炸弹。
v1.4.0 的改动,本质上是把这个模型拆碎了重建:从「一条流式查询整表拉完」升级为 keyset 分块 + 每块提交 + 检查点断点续传。
拆开看:
- keyset 分块:不再一条查询拉全表,而是按主键(或唯一有序键)切块,每块一次查询;
- 每块提交:每一块写入目标库后立即提交,不再攒一个大事务;
- 检查点断点续传:崩溃或 kill 进程后,从上一个检查点(即上一块)继续,不再整表重来。
这三个动作是环环相扣的。没有分块,就没有提交粒度;没有每块提交,检查点就没有意义——你没法在一个没提交的大事务中间打点。所以这不是三个独立优化,而是一个完整的可靠性模型重构。
🔋 为什么不用 OFFSET 分页
有人会问:分块拉数据,为什么不用最常见的 LIMIT/OFFSET 分页?
答案是 OFFSET 在大数据量下是性能灾难。OFFSET 100 万,数据库要把前 100 万行也扫一遍才能给你返回第 100 万零一行。表越大,越往后翻,每次查询越慢,整体复杂度是 O(n²)。
keyset 分块(keyset pagination)避开这个问题。它用「上一块的最后一个键值」作为下一块的起点,每次查询都是 WHERE key > last_key ORDER BY key LIMIT n。数据库直接走索引定位起点,每次查询成本恒定,整表复杂度 O(n)。
这是分页方案里工程上最扎实的一种。代价是要求分块键上有索引且有序——所以 keyset 通常落在主键上,这也是为什么 Jync 这次的表内并行会限定条件(后面讲)。
⚡ 表内并行:MIN/MAX 切区间
可靠性解决了,接下来是吞吐。
v1.4.0 给单列整数主键的表提供了一个开关:表内并行,至多 8 个 worker。
原理很朴素:用 MIN(主键) 和 MAX(主键) 拿到整表主键范围,然后把区间切成 N 份,每个 worker 负责一个不重叠区间,各自独立拉取、独立提交。
关键在「切不重叠区间」这五个字。不重叠,意味着 worker 之间没有数据竞争、没有边界冲突,不需要协调,也不需要去重。每个区间天然是独立的事务单元,一个 worker 挂了只影响自己那个区间,其他 worker 不受牵连——这和检查点机制天然契合:每个区间内部还可以用 keyset 继续
切块续传。
为什么限定「单列整数主键」?因为整数才能做均匀的数值切分。复合主键、字符串主键、UUID 主键,要么切不均,要么没法直接比大小。这是个务实的取舍:先覆盖最常见的场景(自增 ID 主键表),而不是追求通用性把所有主键类型都塞进来。
💡 Oracle 增量游标:ROWDEPENDENCIES 的价值
全量装载之外,v1.4.0 在增量同步侧也补了一块:Oracle 源新增行级 ORA_ROWSCN 增量游标。
ORA_ROWSCN 是 Oracle 给每行维护的系统变更号(SCN),可以用来判断「这行最后一次被修改是什么时候」。拿它当增量游标,理论上就是:上次同步到 SCN X,这次查 WHERE ORA_ROWSCN > X,拿到所有新变更。
但这里有个坑:默认情况下,ORA_ROWSCN 记录在块级,同一数据块里的行共享一个 SCN,只要有任何一行变更,整块所有行的 ORA_ROWSCN 都会变。这会导致大量误报——本来没变的行也会被当成变更行捞出来,增量同步的吞吐和正确性都受影响。
解法是建表时带 ROWDEPENDENCIES 属性。加上之后,Oracle 会在行级维护 SCN,ORA_ROWSCN 才精确到行。这就是素材里那句「建表带 ROWDEPENDENCIES 的表,已同...」——只有这类表才能享受行级增量游标的精度,块级 SCN 的表用这个游标会大量重复捞取。
对比一下另一种常见做法,基于时间戳字段的增量(比如 updated_at),ORA_ROWSCN 有几个优势:
1. 不依赖业务表里恰好有靠谱的时间戳字段;
2. 不依赖应用每次都正确更新时间戳;
3. 数据库系统级维护,不占业务字段、不占应用逻辑。
代价是它绑定 Oracle,且要求建表属性配合。这是一个典型的「特定源库专属优化」——通用同步工具做通用抽象,但它愿意为某个源库的独有能力做专门适配,这种投入通常只有认真做深源支持的工具才愿意付出。
⚠️ 一个务实派同步工具的样子
把 v1.4.0 的改动放在一起看,能看出 Jync 的产品哲学:
1. 版本主题聚焦:一个版本就押一个核心问题(v1.4.0 就是全量装载),不撒胡椒面;
2. 取舍明确:表内并行先只支持单列整数主键,不追求大而全;
3. 源库深度适配:愿意为 Oracle 的 ROWDEPENDENCIES 做专门优化;
4. 可靠性优先于功能广度:断点续传这种不性感但致命的能力,排在花哨功能前面。
据多位一线数据工程师的说法,全量装载断点续传这个能力,在选型时经常被忽略,等到真出事才发现是刚需。很多同步工具的对比评测都在卷 CDC 性能、卷延迟数字,但真正决定用户去留的,往往是凌晨三点那次崩溃后,工具能不能从上一块继续。
异构数据库同步这个赛道,通用抽象(Apache SeaTunnel、DataX 这类)和专深适配(Flink CDC、CloudCanal 这类)各有拥趸。Jync 这次版本的更新方向表明,它选择把工程可靠性和吞吐这两件事做透,而不是急着堆功能列表。
对用户来说,这版更新的信号很清楚:如果你的场景里全量装载占比高(冷启动迁移、定期重建、大批量补数),v1.4.0 的检查点断点续传和表内并行,值得认真评估。
数据管道的可靠性,从来不靠架构图上的漂亮抽象,靠的是崩溃之后那一行检查点日志。

“小结:Jync v1.4.0 把初始全量装载从一条流式查询,升级为 keyset 分块 + 每块提交 + 检查点断点续传,配合单列整数主键表的 MIN/MAX 区间并行(至多 8 worker),以及 Oracle 源基于 ROWDEPENDENCIES 的行级 ORA_ROWSCN 增量游标。这一版没有新概念,全是工程硬活,恰好印证了一个朴素的判断:同步工具的护城河,不在 demo 里,在凌晨三点的崩溃恢复里。