我已经阅读了马丁·福勒的书Optimistic Offline Lock
作者描述了以下示例(如果我正确理解的话:]
有2个实体:Order
和Client
。有2个交易(业务):
第一笔交易计算订单的税额。税额取决于订单点和客户地址
第二笔交易更新客户地址
这里的问题是,如果在计算client
的税额时更改order
地址,结果可能会不一致。作者提供了两种基于乐观脱机锁定的解决方案。其中之一是在交易开始时检查order
和client
版本,并在交易结束时检查order
和client
版本。但是在这里作者警告说,我们必须使用REPEATABLE READ
隔离级别或更高的隔离级别才能再次读取版本。这是我提出问题的原因。据我了解,如果我第二次读取任何行,我将得到相同的结果,因为在使用此隔离级别时,数据库将锁定我们之前已阅读的所有行。
请向我解释作者的想法。
DB仅在需要时才锁定我们已阅读的所有行。 REPEATABLE READ
隔离级别是所需的最低级别。从PG文档:
Read Committed是PostgreSQL中的默认隔离级别。当事务使用此隔离级别时,SELECT查询(不包含FOR UPDATE / SHARE子句)仅查看在查询开始之前提交的数据;否则,查询不可用。它永远不会看到并发事务执行查询期间提交的数据或未提交的更改。实际上,SELECT查询从查询开始运行时就可以看到数据库的快照。但是,SELECT确实会看到在其自己的事务中执行的先前更新的效果,即使尚未提交也是如此。还请注意,即使其他事务在第一个SELECT开始之后且在第二个SELECT开始之前提交更改,即使两个连续的SELECT命令在单个事务中,它们也可以看到不同的数据。
因此,如果您以REPEATABLE READ +
隔离级别运行,则更新将成功(版本为“稳定”),但是如果另一个事务更改了版本字段,则您的事务将无法提交。
如果您以READ COMMITTED
隔离级别运行,并且另一个事务在此之前更改了版本字段,则UPDATE将不会更新任何内容(executeUpdate
将返回0)。因此,您可以检查并采取相应措施。
底线,两个选项都可以使用,但是行为并不相同,您的代码应具有不同的行为。如果您使用ORM,请仔细检查其行为。