在关系数据库中安全并发更新的好方法是什么?

时间:2014-02-28 12:50:07

标签: java concurrency database-concurrency

我正在编写一个Java应用程序来更新关系数据库(目前为H2)。我有一个执行以下操作的过程:

  1. 查询外部系统中的某些数据项
  2. 检查这些项目是否已经导入我们的系统 检查导入日志表。如果不是:
  3. 将新数据项导入各种表。
  4. 将新记录写入导入日志 表
  5. 此进程可能在不同的线程中并发运行。我想避免两个线程可能都检查导入日志,在那里找不到任何内容,然后两个都试图插入数据项的问题。

    什么可能是一个好方法?我一直在考虑:

    1. 使用SERIALIZABLE事务隔离。
    2. 依赖导入日志中的唯一索引约束来发送错误并回滚其中一个事务。
    3. 将流程限制在Java应用程序中的单个线程。
    4. 由于各种原因,以上所有内容都不具吸引力 - 是否有其他方法可能更好?

2 个答案:

答案 0 :(得分:0)

我会颠倒你的过程。我没有轮询源代码进行更改,而是让源代码将更改写入队列(我想到了JMS,但它可能是任何队列)。这将使您的工作更轻松,并且可能具有更好的性能。

在外部系统中执行此操作就像在数据库中添加一些触发器或在持久层中添加任何侦听器(如果有的话)一样简单,就像任何审计过程一样。

当然,只有控制源数据时,此选项才有意义。

为什么需要很多线程来进行同步?

答案 1 :(得分:0)

SERIALIZABLE事务隔离肯定是实现目标的最确定的方法,但它可能意味着性能会受到影响。

您没有考虑过一个选项,那就是建立自己的信号量。

您可以创建当前正在处理的项目的静态ConcurrentHashMap,并且(在每个插入过程开始时 - 放置一条记录,完成后删除它。

然后每个Thread进程可以在开始插入之前查询此信号量。