如何正确处理两个线程更新数据库中的同一行 [英] How to properly handle two threads updating the same row in a database

查看:269
本文介绍了如何正确处理两个线程更新数据库中的同一行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 T1 的线程,用于读取平面文件并解析它。我需要创建一个名为 T2 的新线程来解析这个文件的某些部分,稍后这个 T2 线程需要更新原始实体的状态,原始实体也被原始线程 T1 解析和更新。我如何处理这种情况?

I have a thread called T1 for reading a flat file and parsing it. I need to create a new thread called T2 for parsing some part of this file and later this T2 thread would need to update the status of the original entity, which is also being parsed and updated by the original thread T1.How can I handle this situation?

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

I receive a flat file having the below sample records:

AAAA
BBBB
AACC
BBCC
AADD
BBDD

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

First this file is saved in database in Received status. Now all the records starting with BB or with AA need to be processed in a separate thread. Once it's successfully parsed, both threads will try to update the status of this file object in a database to Parsed. In some cases, I get staleObjectException. And the work done by any thread before the exception is lost. We are using optimistic locking. What is the best way of avoiding this problem?

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

以上帖子有助于理解其中的一部分,但它无助于解决我的问题。

The above post helps to understand some part of it, but it does not help to resolve my problem.

推荐答案

第1部分 - 您的问题 - 我看到它的方式。

Part 1 - Your problem - the way I see it.

您收到此异常的主要原因是您正在使用Hibernate可能<强>乐观锁定。这基本上告诉你线程T1或线程T2已经将状态更新为PARSED,现在另一个线程持有旧版本的行,其版本比数据库中保存的版本小,并尝试将状态更新为PARSED 。

The main reason for you receiving this exception is that you are using Hibernate with possibly optimistic locking. This basically tells you that either thread T1 or thread T2 have already updated the state to PARSED and now the other thread is holding old version of the row with smaller version than the one held in the database and trying to update the state to PARSED as well.

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

The big question here is "Are the two threads trying to preserve the same data?". If the answer to this question is yes then even if the last update succeed there shouldn't be any problem, because eventually they are updating the row to the same state. In that case you don't really need Optimistic locking because your data will, in any case be in sync.

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

The main problem comes if after the state is set to RECIEVED if the two threads T1 and T2 actually depending on one another when reseting to the next status. In that case you need to ensure that if T1 has executed first(or vice versa) T2 needs to refresh the data for the updated row and re-apply its changes based on the changes already pushed by T1. In this case the solution is the following. If you encounter staleObjectException you basically need to refresh your data from the database and restart your operation.

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

Part 2 analysis on the link posted Possible hibernate exceptions when two threads update the same Object? Approach 1, this is more or less the last to update Wins situation. It more or less avoids the optimistic locking (the version counting). In case you don't have dependency from T1 to T2 or reverse in order to set status PARSED. This should be good.

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

****Aproach 2** Optimistic Locking** This is what you have now. The solution is to refresh the data and restart your operation.

Aproach 3行级数据库锁此处的解决方案或多或少与对于方法2,使用悲观锁定的小修正。主要区别在于,在这种情况下,它可能是一个READ锁,如果它是PESSIMISTIC READ,你可能甚至无法从数据库中读取数据以进行刷新。

Aproach 3 Row level DB lock The solution here is more or less the same as for approach 2 with the small correction that the Pessimistic lock dure. The main difference is that in this case it may be a READ lock and you might not be even able to read the data from the database in order to refresh it if it is PESSIMISTIC READ.

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

Aproach 4 application level synchronization There are many different ways to do synchronization. One example would be to actually arrange all your updates in a BlockingQueue or JMS queue(if you want it to be persistent) and push all updates from a single thread. To visualize it a bit T1 and T2 will put elements on the Queue and there will be a single T3 thread reading operations and pushing them to the Database server.

如果你使用在应用程序级同步时,您应该知道在多服务器部署中不能分发所有结构。

If you use application level synchronization you should be aware that no all structures can be distributes in a multi-server deployment.

我现在想不出任何其他内容:)

Well I can't think of anything else for now :)

这篇关于如何正确处理两个线程更新数据库中的同一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆