java在事务中使用“上次修改”时间戳同步Oracle数据库
我们有一个企业级Oracle 12c数据库,我们希望使用Java程序(在同步过程中会进行大量聚合)与分析数据库同步,使用Oracle数据库中每行的“上次修改”时间戳来确定需要同步的行。一般算法是
void run() {
Timestamp lastRead = loadLastRead(); // load last logged timestamp
while(true) {
rows = select * from Oracle database where last_modified >= lastRead;
lastRead = rows.max(last_modified); // max timestamp from the retrieved rows
saveLastRead(lastRead); // log the timestamp in case the program crashes
sleep(five minutes or whatever);
}
}
我担心我可能会遇到以下情况:
- 事务从第R1行开始,计算T1的时间戳
- 上次修改的时间戳T2写入第R2行
- 使用T0的lastRead进行同步
- 同步结束,lastRead更新为T2
- 时间戳为T1的事务提交<;第R1行的T2
现在我将永远不会同步行R1(直到新数据写入其中,假设我没有再次被事务挫败)。我可以尝试最小化时间戳偏移,但我看不到消除它的方法
一个解决办法是做如下事情
lastRead = rows.max(last_modified) - C;
其中C是5秒或其他一些我们认为很多事务不会超过的时间跨度-问题是,如果C太大,我们将重新同步太多的数据,如果C太小,我们可能会得到一些超出C的异常事务
另一个解决方案是使用每行版本号,这将需要大量的簿记工作,几乎肯定会影响select * from Oracle database
的性能
# 1 楼答案
诚然,尝试使用基于时间戳列的查询并不是获取更改的可靠方法,除非您引入了显著的延迟或系统停机(例如,在不太可能进行并发更改时运行过夜批处理)
有些人使用的另一种方法是基于有序Oracle序列使用单调递增的数字ID列。这种方法的一个问题可能是有序序列在RAC系统中如何执行
A Materialized View(如Lalit所建议)将是一种选择
根据您的预算和需求的复杂性,其他一些选项包括:
Change Data Capture
Oracle GoldenGate
Oracle Data Integrator(ODI)
注:GoldenGate和ODI是互补产品,可以很好地协同工作
# 2 楼答案
您可以使用
MATERIALIZED VIEW
来保持数据同步。您不必手动为此编写程序,Oracle
将为您完成这项工作您可以在文档https://docs.oracle.com/database/121/SQLRF/statements_6002.htm#SQLRF01302中阅读有关物化视图的更多信息