Hibernate 和 PostgreSQL:REPEATABLE_READ 和使用@Version 注解来避免写入倾斜和其他现象
Posted
技术标签:
【中文标题】Hibernate 和 PostgreSQL:REPEATABLE_READ 和使用@Version 注解来避免写入倾斜和其他现象【英文标题】:Hibernate and PostgreSQL: REPEATABLE_READ and use of @Version annotation to avoid write skews and other phenomena 【发布时间】:2021-12-17 18:14:20 【问题描述】:我正在使用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 上使用可重复读取,只有写入倾斜是可能的。但是使用乐观锁定,不会发生不一致。这个想法对吗?
【问题讨论】:
【参考方案1】:在 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;
两个事务都成功了,但是你得到了写偏斜。
【讨论】:
那么,事务 1 永远不会看到 Bob 不在值班,对吧? 对。REPEATABLE READ
意味着您仍然会看到与 SELECT name, version FROM worker WHERE on_duty;
相同的结果,即使并发事务已修改并提交了该值。我意识到我的回答打错了;其中一项交易应该更新 Alice。
是的,我现在可以清楚地看到写入倾斜!以上是关于Hibernate 和 PostgreSQL:REPEATABLE_READ 和使用@Version 注解来避免写入倾斜和其他现象的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate 3:无法查询 PostgreSQL 数据库
long 类型的错误值:- Postgresql、Hibernate、Spring
将 PostgreSQL 9.2.1 与 Hibernate 连接起来
不能用Hibernate调用PostgreSQL的11个存储过程