我们有一个企业级 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 的时间戳
- 写入 R2 行的last_modified 时间戳 T2
- 使用 T0 的 LastRead 进行同步
- 同步结束,lastRead 更新为 T2
- 事务在 R1 行上提交,时间戳为 T1 < T2
现在我永远不会同步行 R1(直到新数据写入其中,假设我没有再次被事务阻止)。我可以尝试最小化时间戳偏差,但我没有找到消除它的方法。
一种解决方案是执行类似的操作
lastRead = rows.max(last_modified) - C;
其中 C 是五秒或其他一些我们认为许多事务不会超过的时间跨度 - 问题是,如果 C 太大,我们将重新同步太多数据,而如果 C 太小,我们将重新同步太多数据。 C 我们可能会得到一些超过 C 的异常交易
另一种解决方案是使用每行版本号,这需要大量的簿记工作,并且几乎肯定会损害 select * from Oracle Database
最佳答案
确实,尝试使用基于时间戳列的查询并不是获取更改的可靠方法,除非您引入显着的延迟或系统停机时间(例如,当不太可能进行并发更改时运行过夜批处理) )。
一些人使用的另一种方法是使用基于 ORDERed Oracle 序列的单调递增数字 ID 列。这种方法的一个问题可能是有序序列在 RAC 系统中的执行方式。
一个Materialized View (正如 Lalit 所建议的)是一种选择。
根据您的预算和要求的复杂性,其他一些选项包括:
注意:GoldenGate 和 ODI 是互补产品,可以很好地协同工作。
关于java - 面对事务时使用 "last modified"时间戳同步 Oracle 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27285371/