不可重复的读取,丢失的更新,幻像读取以及脏读取与事务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