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

Posted

技术标签:

【中文标题】如果我需要第二次读取版本,为啥要使用可重复读取(或更高)隔离级别?【英文标题】:Why should I use Repeatable Read(or higher) isolation level if I need to read version the second time?如果我需要第二次读取版本,为什么要使用可重复读取(或更高)隔离级别? 【发布时间】:2020-02-11 12:19:02 【问题描述】:

我读过 Martin Fowler 的书籍章节Optimistic Offline Lock

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

有 2 个实体:OrderClient。涉及两笔交易(业务):

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

    第二次事务更新客户端地址

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

请解释一下作者的想法。

【问题讨论】:

【参考方案1】:

我也很难理解书中的那部分。但是,似乎一切都很容易。首先让我从书中复制那段:

没有理由不能使用 Optimistic Offline Lock 来检测 读取不一致。在上面的例子中,电荷产生 session 需要认识到它的正确性取决于值 客户的地址。因此它应该执行版本检查 也在地址上,也许通过将地址添加到更改中 设置或维护要进行版本检查的项目的单独列表。这 后者需要更多的工作来设置,但会导致代码 更清楚地表明了它的意图。 如果您要检查是否一致 只是通过重读版本而不是人为更新来阅读, 请特别注意您的系统事务隔离级别。这 版本重读仅适用于可重复读取或更强 隔离。任何较弱的东西都需要增加版本。

这里作者的意思是,在可重复读取和更强大的事务级别的情况下,您也可以克服这些问题。您将在事务开始时选择客户端地址,Repeatable-Read 将锁定表中的该行,因此第二个事务无法更改任何地址信息。

要记住的重要细节是:

在可重复读取的情况下,事务期间获取的每个锁在事务期间保持

【讨论】:

【参考方案2】:

DB 仅在需要时才会锁定我们之前读取的所有行。 REPEATABLE READ 隔离级别是需要它的最低级别。来自 PG 文档:

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

如果您使用REPEATABLE READ + 隔离级别运行,您的事务会在记录中持有读锁。所以更新要么成功要么回滚整个事务(如果另一个事务试图执行相同的 PG 发生死锁,则会杀死一个事务来解决它)。

如果您使用READ COMMITTED 隔离级别运行,您不会持有锁。如果另一个事务在您之前更改了版本字段,您的 UPDATE 将不会更新任何内容(executeUpdate 将返回 0)。所以你可以检查它并采取相应的行动。

底线,两个选项都可以使用,但行为不一样,你的代码应该表现不同。如果您使用 ORM,请仔细检查其行为。

【讨论】:

1.我没有明白你在关于可重复阅读的段落中的意思(引用后)你能改写一下吗?我的意思是,如果我们能够以可重复读取隔离级别读取数据 - 这意味着其他事务无法在我们的事务终止之前修改这些行。 2.对于马丁·福勒想说什么,我也没有得到答案?

以上是关于如果我需要第二次读取版本,为啥要使用可重复读取(或更高)隔离级别?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在可重复读取中会发生写入偏斜?

RabbitMQ第一次不能正常读取第二次正常的问题

第二次考试:错题总结

如果读写是原子的,为啥需要 volatile [重复]

第一次安装过visual studio2005删了,再第二次安装就安装不起来了!为啥?

为啥微信小程序进入不了第二次