加一张临时表,OceanBase Oracle 写入居然快了 30 倍!

把数据同步到 OceanBase Oracle 模式时,常会遇到一种诡异的慢:JDBC batch 开了、并发也拉满了,监控里增量 RPS 长期在 10 上下,单次写入耗时冲到二十多万毫秒,写入队列一路堆积。

问题通常不在配置,而在一个被忽视的细节:JDBC batch 调用成功,不等于数据库服务端真的做了集合化执行。

CloudCanal v6.3.0.0 (2026 年 7 月 30 日发布)引入 临时表合并模式(Staging Merge) 专门解决此问题。OceanBase Oracle 模式实测:执行写入耗时从 25 万 ms 压到约 8600 ms,快了约 30 倍,RPS 从约 10 提到 700+。本文剖析根因以及 Staging Merge 的实现方式。

batch 开了,为什么写入还是慢?

拖慢 OceanBase Oracle 写入的,通常是两个场景。

场景一:batch MERGE 在服务端"失效"

数据同步到 OceanBase Oracle 模式时,遇到主键冲突通常要用 MERGE INTO ... USING ... ON ... 实现"存在则更新、不存在则插入"。客户端代码看起来规规矩矩:

plain 复制代码
ps.addBatch();
ps.executeBatch();

addBatch() / executeBatch() 只代表 JDBC 把请求批量发出去了 ,不代表服务端把多行改写成一条集合 SQL。在 OceanBase Oracle 模式下实际排查,经常会看到服务端仍在执行 N 次单行 MERGE------也就是说,batch 在服务端层面"失效"了。

表现到监控上(优化前):

  • 增量 RPS 长期在 10 上下,几乎没有有效吞吐
  • 执行写入耗时峰值 25.4 万 ms
  • 写入队列等待时间超 10 亿 ns,数据基本堵在队列里

场景二:高频 INSERT/UPDATE/DELETE 把 batch 切碎

增量同步的数据按源端事务和日志事件到达。哪怕同一张表短时间内涌入大量数据,只要事件类型不停切换:

plain 复制代码
INSERT -> UPDATE -> DELETE -> UPDATE -> INSERT ...

普通批量写入只能按操作类型分开执行。本可以合并的一组同表数据,被切成大量只有几行、几十行的小批次。直接后果:

  • 目标表被反复 INSERT / UPDATE / DELETE / MERGE,同一主键短时间内被多次探测和修改
  • executeBatch() 调用次数暴增,小事务刷盘与提交开销叠加
  • batch 越碎,参数绑定和网络交互的固定成本占比越高

根因:batch API 成功 ≠ 服务端集合执行

很多人以为"调了 executeBatch() 就是批量写入"。实际上 JDBC batch 解决的是客户端到服务端的网络往返成本,它不保证服务端把多条 DML 合并成一条集合化执行计划。

具体到 OceanBase Oracle 模式,这个问题集中体现在 MERGE 上:客户端发出去的是一条批量 MERGE,服务端却没有把它改写成集合执行,而是拆成 N 次单行 MERGE 逐条跑,batch 的集合化收益完全拿不到。这不是个例------OceanBase 官方知识库 也收录了这一现象:Oracle 模式下批量语句常常无法启用 BATCH 优化。结果就是:你以为发出去的是 1 条批量 MERGE,服务端其实跑了 1024 次单行 MERGE。

所以优化方向不是"再多开几个并发",而是让服务端真正集合化执行------用一条集合 SQL 把同一批数据一次处理掉。

解法:CloudCanal Staging Merge

Staging Merge 用一条统一路径同时解决上面两个问题:先把一批数据批量写入 staging 临时表,再通过集合 SQL 修改目标表。

plain 复制代码
业务数据
  -> JDBC batch insert staging table
  -> DELETE / MERGE target using staging table
  -> commit / 清理 session 数据

关键在于换一种写入形态:不再指望服务端把批量 MERGE 改写成集合执行,而是先把整批数据用批量 INSERT 灌进临时表(实测单次可写入上千行),再由集合 SQL 一次性改完目标表------比如一条 MERGE INTO 目标表 USING 临时表,本身就是集合执行,跟 batch 改写无关。原本的 1024 次单行 MERGE,就这样被压缩成 1 条集合 MERGE。

为什么用临时表,不直接改目标表?

因为集合 MERGE 需要 source 数据。OceanBase / Oracle 的 GLOBAL TEMPORARY TABLE(GTT)天然适合做这个 source:

  • 结构全局可见,数据 session 私有,不同连接互不影响
  • ON COMMIT DELETE ROWS 让连接 commit 后自动清理 staging 数据

开启方式与适用范围

Staging Merge 通过两个新参数开启:

  • useStagingMerge:开启临时表合并模式
  • stagingSchema:指定临时表所在的 schema,临时表会集中建在这个 schema 下便于管理

OceanBase for Oracle 目标端在全量、增量阶段均可启用该模式。

效果:RPS 从 10 提到 700

下面这组实测数据来自 **OceanBase for Oracle(Oracle 租户模式)**目标端。

同样的环境:阿里云 ECS 8C16G、184 列宽表、writeParallel 32、increBatchSize 1024,全程无 CPU / 内存瓶颈。

OB Oracle batch MERGE 失效场景

优化前:

开启 useStagingMerge 后:

  • 增量 RPS 从 ~10 提升到 479(均值)~ 718(峰值)
  • 执行写入耗时从 25.4 万 ms 压到 约 8600 ms ,快了约 30 倍
  • 写入队列等待时间同步回落,数据不再堆积

高频 I/U/D 混合场景

第二个问题也被同一条路径解决。原本会被切成大量小 batch 的混合 I/U/D,先在内存里按主键压缩成最终状态,再用"集合 DELETE + 集合 MERGE"两条 SQL 一次性落库,省掉大量目标表反复探测和小事务提交开销。以 MySQL → OceanBase Oracle 实测为例:

同一套机制也适用于 Oracle 目标端。

混合 DML 如何收敛成两条集合 SQL

对于同一张表里交错的 INSERT/UPDATE/DELETE,Staging Merge 会先在内存里按主键算出每个主键的最终状态,再收敛成两条集合 SQL 一次性落库:需要删的主键走一条集合 DELETE,需要写或更新的走一条集合 MERGE。

压缩的关键不是简单取最后一行,而是要识别最后一次 INSERT 和 DELETE 的相对位置,保证结果正确:

原始事件序列 压缩后目标动作
INSERT -> UPDATE -> UPDATE 只写最终值一次
UPDATE -> UPDATE -> DELETE 只删除一次
DELETE -> INSERT -> UPDATE 删旧行后写最终值
INSERT -> DELETE 最终不保留

适用场景与代价

收益

  • 高冲突批量写入性能更稳
  • 大幅减少服务端单行 MERGE 执行次数
  • 高频 I/U/D 交错时,多个小 batch 收敛为少量集合 DML
  • 宽表场景比单行 MERGE 更友好

代价

  • 会在目标库的指定 schema 下自动创建临时表,任务删除时自动清理,无需手动管理

快速开始

如果你正在做 OceanBase for Oracle(或 Oracle)方向的数据同步,遇到类似的写入瓶颈,可以升级到 CloudCanal v6.3.0.0 ,开启 useStagingMerge

老用户一键升级到 v6.3.0.0(Docker 托管镜像版):

bash 复制代码
curl -fsSL https://tgzdownload.clougence.com/support/upgrade_on_docker.sh | bash -s -- 6.3.0.0 ./cc_home

新用户一键安装(Docker 托管镜像版):

bash 复制代码
curl -fsSL https://tgzdownload.clougence.com/support/install_on_docker.sh | bash -s -- 6.3.0.0 ./cc_home

./cc_home 为安装目录,可按需调整。安装完成后浏览器访问 http://<你的机器 IP>:8111 进入控制台。完整步骤见 安装文档 / 升级文档

部署或使用中遇到任何问题,欢迎联系技术支持。

相关推荐
tju23331 小时前
信创产业二十年:国产基础软件走到哪一步了?
数据库·gitee
东方护航数据恢复(深圳)2 小时前
RAID5单盘故障后阵列状态分析与重建风险评估_东方护航数据恢复深圳店
大数据·数据库
会编程的土豆2 小时前
GORM 常见操作从入门到能写 DAO
数据库·gorm
A15362552 小时前
2026 电商物流系统推荐:多渠道仓配履约数字化选型指南
大数据·数据库·人工智能
ClouGence4 小时前
CloudDM:开源免费!一站式数据库访问、SQL审核、权限与脱敏管控平台
数据库·sql·开源
(轻舟已过万重山)4 小时前
第39章 评估迭代:上线只是开始,迭代才是关键
大数据·数据库·人工智能
oradh4 小时前
Oracle参数文件(PFILE与SPFILE)维护操作总结
数据库·oracle·oracle参数·spfile·pfile
l1t4 小时前
kryonix提交的DuckDB 统一并优化标量执行器基础设施 - #24564 PR
开发语言·数据库·数据仓库·sql
鸽芷咕5 小时前
【金仓数据库征文】从 Oracle 到金仓:一次零误差的数据库国产化迁移实录
数据库·oracle