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

标签 java database multithreading hibernate locking

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

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

AAAA
BBBB
AACC
BBCC
AADD
BBDD

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

Possible hibernate exceptions when two threads update the same Object?

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

最佳答案

第 1 部分 - 您的问题

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

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

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

第 2 部分链接分析 Possible hibernate exceptions when two threads update the same Object? 方法 1,这或多或少是最后更新 Wins 的情况。它或多或少避免了乐观锁定(版本计数)。如果您没有从 T1 到 T2 的依赖性或反向以设置状态 PARSED。这应该不错。

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

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

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

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

好吧,我暂时想不出别的了:)

关于java - 如何正确处理两个线程更新数据库中的同一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38303012/

相关文章:

JAVA 剩余两个日期路径参数或查询参数

database - 添加基于 kdb 中其他列值的过滤器

php - 我应该如何查询 MySQL 以及如何缓存 MySQL 的结果?

java - 复杂的Spring框架服务层

c# - 如何安全地使用在任意线程上进行回调的库

java - 处理控制台输入(换行)

java - 保存使用graphics2d、java绘制的缓冲图像

java 。重新声明类初始值设定项内的类字段和方法嵌套 block (框架大括号)差异中的局部变量

php - 提交按钮更新查询

c++ - openmp:增加线程数会降低性能