java多线程一次更新数据库中的同一行如何保持一致性
在我的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 ??
# 1 楼答案
以这种方式递增计数器很难同时管理。你真的需要使用悲观锁来解决这个问题
这将迫使每个线程在读取计数器之前等待上一个线程提交
这是必要的,因为您有两个潜在问题,第一个是读竞争,第二个是写锁。在大多数RDBMS中,写锁是自动获取的,但除非在读取之前显式获取,否则两个线程一起将计数器增加一次(因为两个线程都在更新之前读取原始值)
如果需要并行写入,那么需要插入一个表,然后在以后具体化一个聚合。不过,这是一种更复杂的设计模式
# 2 楼答案
有两种可能的方法
要么选择悲观的方法,锁定行、表甚至行的范围
或者使用版本化实体(乐观锁定)
也许你可以在这里找到更多信息:
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html
# 3 楼答案
以下是对这个问题的详细回答: How to properly handle two threads updating the same row in a database 总结一下:
最大的问题是:两个线程是否试图持久化相同的数据?总结链接答案的内容。让我们把这两个线程命名为T1和T2。这里有几条建议:
方法1,这或多或少是最后一次更新Wins的情况。它或多或少避免了乐观锁定(版本计数)。以防您没有从T1到T2的依赖关系,或者反向设置解析状态。这应该很好
这就是你现在拥有的。解决方案是刷新数据并重新启动操作
一个3行级别的DB锁这里的解决方案与方法2的解决方案大致相同,带有悲观锁造成的小修正。主要的区别是,在这种情况下,它可能是一个读锁,如果是悲观读,您甚至可能无法从数据库中读取数据以刷新它
Aproach 4应用程序级同步有许多不同的同步方法。一个例子是将所有更新实际安排在BlockingQueue或JMS队列中(如果您希望它是持久的),并从单个线程推送所有更新。为了将其可视化,T1和T2将把元素放在队列上,并且将有一个T3线程读取操作,并将它们推送到数据库服务器