Java 多线程数据库访问 [已关闭]

对于多线程 Java 应用程序,确保所有线程同步访问数据库的最佳解决方案是什么?例如,每个线程表示单独的事务,并且首先检查db的值,然后根据答案必须在数据库中插入或更新一些字段(注意检查,插入和提交应用程序之间正在执行其他处理)。但问题是,另一个线程可能在同一个表上做同样的事情。

更具体的例子。线程 T1 启动事务,然后检查表ENTITY_TABLE代码为“111”的条目。如果找到更新其日期,如果未找到,则插入新条目,则提交事务。现在想象一下线程 T2 执行完全相同的操作。现在有几个问题:

  1. T1 和 T2 检查 db,但未发现任何内容,并且都插入相同的条目。
  2. T1 检查 db,查找具有旧日期的条目,但在提交时,T2 已将条目更新到更新到更新的日期。
  3. 如果我们使用缓存并同步访问缓存,我们会遇到一个问题:T1获取锁定检查数据库,如果未找到缓存,则添加到缓存,释放锁定,提交。T2 执行相同的操作,发现缓存中的条目将提交。但 T1 事务失败并回滚。现在T2的形状很糟糕,因为它应该插入ENTITY_TABLE但不知道。
  4. 更多?

我正在努力创建具有同步功能的简单自定义缓存并解决问题3。但也许有一些更简单的解决方案?


答案 1

这应该主要在数据库内通过配置所需的事务隔离级别来处理。然后,最重要的是,您需要选择锁定策略(乐观或悲观)。

如果没有事务隔离,您将很难尝试仅在 Java 域中确保事务完整性。特别是考虑到即使数据库当前仅从 Java 应用程序访问,将来也可能会更改。

现在,至于选择哪个隔离级别,从您的描述中,似乎您需要最高的隔离级别,可序列化。然而,在实践中,由于广泛的锁定,这往往是一个真正的性能猪。因此,您可能希望重新评估您的要求,以找到针对您的特定情况的隔离和性能的最佳平衡。


答案 2

如果要从数据库中对一行进行 SQL SELECT,然后更新同一行,则作为 Java 开发人员,您有 2 种选择。

  1. 使用 ROWLOCK 或特定数据库的任何行锁定语法进行选择。

  2. 选择该行,执行处理,然后在准备更新之前,使用 ROWLOCK 再次选择该行,以查看是否有任何其他线程进行了更改。如果两个 SELECTS 返回相同的值,则 UPDATE。如果没有,请抛出错误或再次进行处理。


推荐