postgresql - Hibernate 和 PostgreSQL:REPEATABLE_READ 和使用@Version 注解来避免写入倾斜和其他现象
问题描述
我正在使用Isolation.REPEATABLE_READ
在 Spring Boot 应用程序中复制大型实体图。它基本上执行 SELECT 和 INSERT。@Version
我还在所有子实体上使用注释使用乐观锁定。我看到即使我在复制执行期间尝试更改实体图中的某些内容,后者也会继续进行,就好像什么都没发生一样。让我们假设从商业角度来看,这是可以接受的。根据 SQL-92 标准,可能发生的现象有:
- 脏读
- 不可重复读取
- 幻读
另外四个(ANSI SQL 隔离级别的批评:https ://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf ):
- 脏写
- 读取偏斜
- 写偏斜
- 丢失更新
据我所知,在 PostgreSQL 上使用可重复读取,只有写入倾斜是可能的。但是使用乐观锁定,不会发生不一致。这个想法正确吗?
解决方案
在 PostgreSQL 上使用可重复读取,只有写入倾斜是可能的
正确的。
但是使用乐观锁定,不会发生不一致。
不,这是不正确的。您可以通过乐观锁定获得“写入偏差”:
CREATE TABLE worker (
name text,
on_duty boolean,
version bigint DEFAULT 0
);
INSERT INTO worker (name, on_duty) VALUES
('alice', TRUE),
('bob', TRUE);
现在有两个事务在表上工作:
Transaction 1 Transaction 2
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT name, version FROM worker WHERE on_duty;
name │ version
═══════╪═════════
alice │ 0
bob │ 0
(2 rows)
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT name, version FROM worker WHERE on_duty;
name │ version
═══════╪═════════
alice │ 0
bob │ 0
(2 rows)
UPDATE worker
SET on_duty = FALSE, version = version + 1
WHERE name = 'bob' AND version = 0;
COMMIT;
UPDATE worker
SET on_duty = FALSE, version = version + 1
WHERE name = 'alice' AND version = 0;
COMMIT;
两个交易都成功了,但是你得到了写偏斜。
推荐阅读
- tensorflow - 索引 = 2 不在 [0, 1) 中
- javascript - Angular 工厂定义打破了需求
- asp.net-mvc - 为 ADFS 身份验证跳过 Home Realm Discovery 页面
- jenkins - Tomcat 上的 Jenkins War 部署
- javascript - 如何从嵌套的 Javascript 数组中读取数据
- php - git避免在发生合并冲突时使用FTP上传文件
- excel - 工作簿表复制到多个工作簿并重命名
- netsuite - NetSuite:从 Suitecommerce 站点获取信息到用户事件脚本
- ios - 在另一个 View Xcode 中显示 ViewController
- c# - PDFClown 无法编辑创建的 PDF