gst*_*low 7 java hibernate transaction-isolation optimistic-locking isolation-level
我读过马丁福勒的书章节 Optimistic Offline Lock
作者描述了以下示例(如果我理解正确的话):
有 2 个实体:Order和Client. 涉及2个交易(业务):
第一个交易计算订单的税额。税额取决于订单点和客户地址
第二笔交易更新客户端地址
这里的问题是,如果在计算税额时client更改地址order,结果可能会不一致。作者提供了两种基于乐观离线锁定的解决方案。其中之一是检查order和client在交易开始时的版本,并检查order和client版本在事务结束。但是这里作者警告我们必须使用REPEATABLE READ隔离级别或更高级别才能第二次读取版本。这是我的问题的一个原因。据我所知,如果我第二次读取任何行,我将得到相同的结果,因为在使用此隔离级别时,DB 会锁定我们之前读取的所有行。
请解释一下作者的想法。
仅当需要时,数据库才会锁定我们之前读取过的所有行。REPEATABLE READ隔离级别是需要它的最低级别。来自 PG 文档:
已提交读是 PostgreSQL 中的默认隔离级别。当事务使用此隔离级别时,SELECT 查询(不带 FOR UPDATE/SHARE 子句)只能看到查询开始之前提交的数据;它永远不会看到未提交的数据或并发事务在查询执行期间提交的更改。实际上,SELECT 查询会看到查询开始运行时数据库的快照。但是,SELECT 确实会看到在其自己的事务中执行的先前更新的效果,即使它们尚未提交。另请注意,如果其他事务在第一个 SELECT 开始之后和第二个 SELECT 开始之前提交更改,则两个连续的 SELECT 命令可以看到不同的数据,即使它们位于单个事务中。
如果您使用REPEATABLE READ +隔离级别运行,您的事务将持有记录上的读锁。因此,更新要么会成功,要么整个事务将被回滚(如果与另一个试图执行相同 PG 的事务发生死锁,则会杀死一个事务来解决它)。
如果您使用READ COMMITTED隔离级别运行,则不会持有锁。如果另一个事务在您之前更改了版本字段,则您的 UPDATE 将不会更新任何内容(executeUpdate将返回 0)。所以你可以检查一下并采取相应的行动。
最重要的是,这两个选项都可以使用,但行为不同,您的代码应该表现不同。如果您使用 ORM,请仔细检查其行为。
| 归档时间: |
|
| 查看次数: |
705 次 |
| 最近记录: |