如何正确处理两个线程更新数据库中的同一行

Gau*_*wal 18 java database multithreading hibernate locking

我有一个线程调用T1读取平面文件并解析它.我需要创建一个新的线程,T2用于解析此文件的某些部分,稍后此T2线程需要更新原始实体的状态,原始线程也会对其进行解析和更新.T1如何处理这种情况?

我收到一个包含以下样本记录的平面文件:

AAAA
BBBB
AACC
BBCC
AADD
BBDD
Run Code Online (Sandbox Code Playgroud)

首先,此文件以Received状态保存在数据库中.现在所有以BBAA需要在单独的线程中处理的记录.一旦成功解析,两个线程都会尝试将数据库中此文件对象的状态更新为Parsed.在某些情况下,我得到了staleObjectException.编辑:在异常丢失之前,任何线程完成的工作.我们正在使用乐观锁定.避免这个问题的最佳方法是什么?

两个线程更新同一个对象时可能出现的hibernate异常?

上面的帖子有助于理解它的某些部分,但它无助于解决我的问题.

Ale*_*rov 13

第1部分 - 你的问题

您收到此异常的主要原因是您正在使用带有乐观锁定的 Hibernate .这主要是告诉你,要么线程T1或线程T2已经更新了状态PARSED现在其他线程持有旧版本的数据行比保存在数据库中的一个较小的版本,并试图更新状态以解析以及.

这里的问题是" 两个线程是否试图保留相同的数据?".如果答案是肯定的,那么即使最后一次更新成功,也应该没有任何问题,因为最终他们将行更新为相同的状态.在这种情况下,您不需要乐观锁定,因为您的数据在任何情况下都是同步的.

如果在重置到下一个状态时两个线程T1和T2实际上彼此依赖,则在状态被设置为RECIEVED之后出现主要问题.在这种情况下,您需要确保如果T1已首先执行(反之亦然),则T2需要刷新更新行的数据,并根据T1已推送的更改重新应用其更改.在这种情况下,解决方案如下.如果遇到staleObjectException,则基本上需要从数据库刷新数据并重新启动操作.

第2部分分析链接发布 当两个线程更新同一个对象时可能出现hibernate异常? 方法1,这或多或少是最后更新Wins的情况.它或多或少地避免了乐观锁定(版本计数).如果您没有从T1到T2的依赖关系或反向以设置状态PARSED.这应该是好的.

Aproach 2乐观锁定这就是你现在拥有的.解决方案是刷新数据并重新启动操作.

Aproach 3行级DB锁定此处的解决方案与方法2大致相同,具有悲观锁定的小修正.主要区别在于,在这种情况下,它可能是一个READ锁,您可能甚至无法从数据库中读取数据,以便在它是PESSIMISTIC READ时刷新它.

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

如果使用应用程序级同步,则应注意不能在多服务器部署中分发所有结构.

好吧,我现在想不出别的:)