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



我正在编写一个Java应用程序来更新关系数据库(目前为H2)。我有一个过程,它做以下事情:

  1. 查询外部系统中的某些数据项
  2. 检查这些项目是否已通过检查导入日志表。如果不是:
  3. 将新的数据项导入到各种表中
  4. 将新记录写入导入日志表

此进程可能在不同的线程中同时运行。我想避免这样的问题,即两个线程可能都检查了导入日志,但没有发现任何内容,然后都试图插入数据项。

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

  1. 使用SERIALIZABLE事务隔离
  2. 依赖于导入日志中的唯一索引约束来错误并回滚其中一个事务
  3. 将进程限制在Java应用程序中的单个线程中

由于各种原因,以上这些似乎都不太吸引人——还有其他方法可能更有效吗?

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

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

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

然后,每个线程进程都可以在开始插入之前查阅这个信号量。

我会反转您的流程。我会让您的源代码将更改写入队列,而不是轮询源代码以获取更改(我想到了JMS,但它可以是任何队列)。这会让你的工作更轻松,可能会有更好的表现。

要在外部系统中做到这一点,只需在DB中添加一些触发器或在持久层中添加任何侦听器(如果有的话),就像任何审计过程一样简单

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

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

最新更新