最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何在Java中使用JDBC完成Oracle数据库的增量同步
时间:2026-07-15 19:52:54 编辑:袖梨 来源:一聚教程网
增量同步必须依赖last_update_time等可识别变更的字段,优先选用带索引的last_update_time,配合PreparedStatement绑定Timestamp参数、分批提交、MERGE幂等写入及断点续传控制表实现可靠同步。
增量同步必须依赖可识别变更的字段
oracle本身不提供全局递增id或自动更新时间戳,所以java端做增量同步前,得先确认源表有没有 last_update_time 或 create_time 这类能反映变更的字段。没有的话,dbms_logmnr 或物化视图日志虽可行,但运维成本高,不建议在jdbc层硬扛。
常见错误现象:用 ROWNUM 或 ROWID 当增量依据——它们不随业务变更稳定递增,重跑时会漏数据或重复插入。
- 优先选
last_update_time(带索引),查询条件写成WHERE last_update_time > ? - 若只有
create_time,且业务只做 INSERT 不 UPDATE/DELETE,则可用;否则无法捕获修改 - 避免用
SYS_GUID()或序列值做判断,无时间语义,无法排序和断点续传
PreparedStatement + 时间参数绑定是核心写法
每次同步需记住上一次最大时间点,下次查询就从这个时间点往后取。不能靠“查 MAX(time) 再 +1 秒”这种粗略方式,Oracle毫秒级时间可能有重复。
示例关键片段:
String sql = "SELECT id, name, value, last_update_time FROM t_user WHERE last_update_time > ?";PreparedStatement ps = conn_source.prepareStatement(sql);ps.setTimestamp(1, lastSyncTime); // lastSyncTime 是上次同步记录的最大时间ResultSet rs = ps.executeQuery();
注意:setTimestamp 必须用 java.sql.Timestamp,不是 java.util.Date;Oracle对时区敏感,确保 JDBC URL 里加了 serverTimezone=UTC 或显式设置 Calendar 实例。
立即学习“Java免费学习笔记(深入)”;
- 查询结果集建议调用
rs.setFetchSize(5000),减少网络往返次数 - 别用
rs.next()配合Thread.sleep()控速——这是反模式,应由数据库限流或应用层队列控制 - 如果源表没索引在
last_update_time上,全表扫描会拖垮性能,务必补建
批量写入目标库要关自动提交 + 分批提交
目标库插入不设事务边界,轻则锁表,重则 ORA-01555 快照过旧错误。尤其当源数据量大、单次拉取超10万行时,必须手动分批。
典型做法:
- 目标连接调用
conn_destination.setAutoCommit(false) - 每 5000 行执行一次
ps_target.executeBatch()+conn_destination.commit() - 捕获
SQLException后,回滚当前批次,记录失败 offset 和时间范围,便于重试 - 避免用
addBatch()堆积百万条再 execute —— 内存溢出风险高,且 Oracle 批处理上限默认是 1000 条/批
断点续传和幂等写入缺一不可
网络抖动、JVM Crash、数据库瞬断都会导致同步中断。只靠“记时间戳”不够,还得在目标表加唯一约束或用 MERGE 语句。
推荐写法:
MERGE INTO t_user_dst tUSING (SELECT ? id, ? name, ? value, ? last_update_time FROM dual) sON (t.id = s.id)WHEN MATCHED THEN UPDATE SET t.name = s.name, t.value = s.value, t.last_update_time = s.last_update_timeWHEN NOT MATCHED THEN INSERT (id, name, value, last_update_time) VALUES (s.id, s.name, s.value, s.last_update_time)
这样即使同一批数据重推,也不会报唯一键冲突或丢更新。
- 每次同步成功后,把本次查询到的最大
last_update_time写入一张控制表(如sync_checkpoint),而不是存在内存或文件里 - 不要依赖 JVM shutdown hook 记 checkpoint —— 容器重启或 kill -9 时它不触发
- Oracle 的
MERGE在 10g 及以上都支持,但注意目标列不能为 NULL 约束而源数据为 NULL,否则报 ORA-01400
相关文章
- 王者荣耀世界零氪玩家如何生存 07-28
- 快手极速版怎么绑定手机号 07-28
- 明日方舟和轻松小熊联动活动内容一览 07-28
- 逆战未来黎明之光 逆战未来黎明之光玩法机制与新手入门指南 07-28
- 植物大战僵尸融合版毁灭土豆地雷介绍 07-28
- 逆战未来飓风之龙 逆战未来飓风之龙武器获取方法详解 07-28