多个线程一次更新数据库中的同一行如何保持一致性

时间:2016-12-23 15:11:38

标签: java database multithreading hibernate concurrency

在我的java应用程序中,多个线程一次更新同一行如何获得一致性结果?

例如

current row value count =0; 
thread 1 updating it to count+1=1;
thread 2 updating at the same time count+1=2

    but it should not happen like this 
    thread 1 updating it to count+1=1;
    thread 2 updating at the same time count+1=1;

    both threads should not catch the same value because both are running same time 


    how can we achieve this in jdbc  hibernate , database ??  

5 个答案:

答案 0 :(得分:2)

有两种可能的方法。

  • 您可以选择悲观方法并锁定行,表甚至行范围。

  • 或者您使用版本化的实体(乐观锁定)。

也许你可以在这里找到更多信息:

https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html

答案 1 :(得分:1)

以这种方式增加计数器很难同时管理。你真的需要使用悲观锁定来解决这个特殊问题。

SELECT 1 FROM mytable WHERE x IS TRUE FOR UPDATE

这将强制每个线程等到上一个线程在读取计数器之前提交。

这是必要的,因为你有两个潜在的问题,第一个是比赛,第二个是锁。写锁定在大多数RDBMS中自动获取,但除非您在读取之前明确地使用它,否则计数器将由两个线程一起一次递增(因为两者都在更新之前读取原始值)。

如果需要进行并行写入,则需要插入表,然后再实现聚合。这是一个更复杂的设计模式。

答案 2 :(得分:0)

您的问题并非100%明确,但我猜您正在寻找不同的锁定策略:http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#locking

答案 3 :(得分:0)

如果您正在使用具有序列生成器的数据库(Oracle,Postgres,...),您应该考虑使用它们。假设你总是做同样的增量值,并且不是一个线程增加一个而另一个增加两个,那么这应该是一个很好的解决方案。

答案 4 :(得分:0)

以下是此问题的详细答案: How to properly handle two threads updating the same row in a database 总结一下:

最大的问题是:这两个线程是否试图保留相同的数据?总结链接答案的内容。让我们命名两个线程T1和T2。有几个方法:

方法1 ,这或多或少是最后一次更新“获胜”的情况。它或多或少避免了乐观锁定(版本计数)。如果您没有从T1到T2的依赖关系,或者为了设置状态PARSED而没有依赖关系。这样应该很好。

Aproach 2乐观锁定,这就是您现在拥有的。解决方案是刷新数据并重新开始操作。

方法3行级DB锁此处的解决方案与方法2大致相同,只是悲观锁所造成的微小修正。主要区别在于,在这种情况下,它可能是READ锁,并且如果是PESSIMISTIC READ,您甚至可能无法从数据库中读取数据以刷新它。

Aproach 4应用程序级同步。有许多不同的同步方法。一个示例是将所有更新实际安排在BlockingQueue或JMS队列中(如果您希望它是持久的),然后从单个线程推送所有更新。为了使它形象化,T1和T2会将元素放入队列,并且只有一个T3线程读取操作并将其推送到数据库服务器。