有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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);
  }
}

我担心我可能会遇到以下情况:

  1. 事务从第R1行开始,计算T1的时间戳
  2. 上次修改的时间戳T2写入第R2行
  3. 使用T0的lastRead进行同步
  4. 同步结束,lastRead更新为T2
  5. 时间戳为T1的事务提交<;第R1行的T2

现在我将永远不会同步行R1(直到新数据写入其中,假设我没有再次被事务挫败)。我可以尝试最小化时间戳偏移,但我看不到消除它的方法

一个解决办法是做如下事情

lastRead = rows.max(last_modified) - C;

其中C是5秒或其他一些我们认为很多事务不会超过的时间跨度-问题是,如果C太大,我们将重新同步太多的数据,如果C太小,我们可能会得到一些超出C的异常事务

另一个解决方案是使用每行版本号,这将需要大量的簿记工作,几乎肯定会影响select * from Oracle database的性能


共 (2) 个答案

  1. # 1 楼答案

    诚然,尝试使用基于时间戳列的查询并不是获取更改的可靠方法,除非您引入了显著的延迟或系统停机(例如,在不太可能进行并发更改时运行过夜批处理)

    有些人使用的另一种方法是基于有序Oracle序列使用单调递增的数字ID列。这种方法的一个问题可能是有序序列在RAC系统中如何执行

    A Materialized View(如Lalit所建议)将是一种选择

    根据您的预算和需求的复杂性,其他一些选项包括:

    注:GoldenGate和ODI是互补产品,可以很好地协同工作