丢失的更新与不可重复的读取有何不同?

正在尝试了解隔离级别和各种问题...即脏读,不可重复读,幻像读和更新丢失。 正在阅读有关Non repeatable read

还阅读了Lost update

让我感到困惑的是,这两个看上去都很相似,即在NRR(不可重复读取)中,Tx B通过Tx A更新了同一行两次读取之间的行,因此Tx A获得了不同的结果。

如果更新丢失-Tx B覆盖Tx A提交的更改 因此在我看来,这两者似乎非常相似且相关。 那是正确的吗?

我的理解是,如果我们使用“乐观锁定”,它将防止出现“丢失更新”的问题 (基于一些非常好的答案here

我的困惑: 但是,这是否也意味着/意味着通过使用“乐观锁定”,我们还消除了“不可重复读取”的问题? 所有这些问题都与带有Oracle数据库的Java J2EE应用程序有关。

注意:为避免分心,我不是在寻找有关脏读和幻像读的详细信息-我目前的重点是完全放在不可重复的读和丢失的更新上

dhtz126 回答:丢失的更新与不可重复的读取有何不同?

不可重复的读取,丢失的更新,幻像读取以及脏读取与事务isolation levels有关,而不是悲观/乐观锁定。我相信Oracle的默认隔离级别是已提交读,这意味着只能防止脏读。

不可重复的读取和丢失的更新确实以某种方式相关,因为它们可能会或可能不会在相同的隔离级别上发生。除非您设置了正确的隔离级别,否则只能通过锁定来避免这两种情况,但是您可以使用版本控制(对每个更新进行检查的列值并在每次更新时递增)至少检测出问题(并采取必要的措施)。

,

可重复读取的目的是提供读取一致的数据:

  • 在查询中,所有结果均应反映数据的状态 特定时间点。
  • 在事务中,相同的查询应返回相同的结果 即使重复。

在Oracle中,从查询开始开始,查询就保持一致。如果数据在查询过程中发生更改,则查询将读取查询开始时存在的数据版本。该版本可在“ UNDO”中找到。

底线:默认情况下,Oracle的隔离级别为READ COMMITTED,它保证查询中而不是事务中的数据保持一致。

您谈论的是Tx A和TxB。在Oracle中,不更改任何数据的会话没有事务。

假定默认隔离级别为READ COMMITTED。假设J2EE应用程序使用连接池并且是无状态的。

  • 应用程序线程A连接到会话X并读取一行。
  • 应用程序线程B连接到会话Y,并使用commit更新行。
  • 应用程序线程A连接到会话Z,并读取同一行,但结果不同。

请注意,这里没有任何数据库可以执行任何操作。即使所有会话都具有SERIALIZABLE隔离级别,会话Z也不知道会话X中正在发生什么。此外,线程A在断开连接时不能将事务挂在会话X中。

对于您的问题,请注意应用程序线程A从未更改任何数据。应用程序线程A背后的人类用户两次查询相同的数据,并看到了两个不同的结果,就是全部。

现在让我们进行更新:

  • 应用程序线程A连接到会话X并读取一行。
  • 应用程序线程B连接到会话Y,并使用commit更新行。
  • 应用程序线程A连接到会话Z,并使用commit更新同一行。

同一行中有三个不同的值,而不是两个。线程A背后的人类用户看到了第一个值,并将其更改为第三个值,却从未看到第二个值!。这就是我们所说的“丢失更新”。

乐观锁定的想法是通知人类用户,在查询数据的时间和要求更新数据的时间之间,其他人首先更改了数据。在确认更新之前,他们应该查看最新的值。

为了简化:

  • 如果您进行查询,则会发生“不可重复的读取”,然后我进行更新,然后您进行查询
  • 如果您进行查询,则会发生
  • “丢失的更新”,然后我进行更新,然后您进行更新。请注意,如果再次查询数据,您需要查看新值,以决定下一步要做什么。

建议阅读:https://blogs.oracle.com/oraclemagazine/on-transaction-isolation-levels

最好的问候,炖阿什顿

本文链接:https://www.f2er.com/3113438.html

大家都在问