如果我需要第二次读取版本,为什么要使用重复读取(或更高版本)隔离级别?

问题描述 投票:2回答:1

我已经阅读了马丁·福勒的书Optimistic Offline Lock

作者描述了以下示例(如果我正确理解的话:]

有2个实体:OrderClient。有2个交易(业务):

  1. 第一笔交易计算订单的税额。税额取决于订单点和客户地址

  2. 第二笔交易更新客户地址

这里的问题是,如果在计算client的税额时更改order地址,结果可能会不一致。作者提供了两种基于乐观脱机锁定的解决方案。其中之一是在交易开始时检查orderclient版本,并在交易结束时检查orderclient版本。但是在这里作者警告说,我们必须使用REPEATABLE READ隔离级别或更高的隔离级别才能再次读取版本。这是我提出问题的原因。据我了解,如果我第二次读取任何行,我将得到相同的结果,因为在使用此隔离级别时,数据库将锁定我们之前已阅读的所有行。

请向我解释作者的想法。

java hibernate isolation-level optimistic-locking transaction-isolation
1个回答
0
投票

DB仅在需要时才锁定我们已阅读的所有行。 REPEATABLE READ隔离级别是所需的最低级别。从PG文档:

Read Committed是PostgreSQL中的默认隔离级别。当事务使用此隔离级别时,SELECT查询(不包含FOR UPDATE / SHARE子句)仅查看在查询开始之前提交的数据;否则,查询不可用。它永远不会看到并发事务执行查询期间提交的数据或未提交的更改。实际上,SELECT查询从查询​​开始运行时就可以看到数据库的快照。但是,SELECT确实会看到在其自己的事务中执行的先前更新的效果,即使尚未提交也是如此。还请注意,即使其他事务在第一个SELECT开始之后且在第二个SELECT开始之前提交更改,即使两个连续的SELECT命令在单个事务中,它们也可以看到不同的数据。

因此,如果您以REPEATABLE READ +隔离级别运行,则更新将成功(版本为“稳定”),但是如果另一个事务更改了版本字段,则您的事务将无法提交。

如果您以READ COMMITTED隔离级别运行,并且另一个事务在此之前更改了版本字段,则UPDATE将不会更新任何内容(executeUpdate将返回0)。因此,您可以检查并采取相应措施。

底线,两个选项都可以使用,但是行为并不相同,您的代码应具有不同的行为。如果您使用ORM,请仔细检查其行为。

© www.soinside.com 2019 - 2024. All rights reserved.