Hibernate 可重复读取和第二次丢失更新问题

Hibernate 可重复读取和第二次丢失更新问题,hibernate,updates,isolation,Hibernate,Updates,Isolation,使用可重复读取隔离级别,仍然可能丢失更新(第二次丢失更新问题)。例如,在隔离级别设置为RR的场景中: 1) 事务t1从行r1读取数据 2) 事务t2从行r1读取相同的数据 3) t1修改在#1中读取的数据,并将数据提交给r1 4) t2修改在#2中读取的数据,并将数据提交给r1。t1的更新丢失 我用Hibernate(隔离级别设置为RR)尝试了这个方法,并看到了上面提到的行为 那么,为什么说使用RR隔离,我们不会遇到第二次丢失更新的问题呢 我用MySQL做了上面的实验,看起来MySQL实现了一个

使用可重复读取隔离级别,仍然可能丢失更新(第二次丢失更新问题)。例如,在隔离级别设置为RR的场景中:

1) 事务t1从行r1读取数据

2) 事务t2从行r1读取相同的数据

3) t1修改在#1中读取的数据,并将数据提交给r1

4) t2修改在#2中读取的数据,并将数据提交给r1。t1的更新丢失

我用Hibernate(隔离级别设置为RR)尝试了这个方法,并看到了上面提到的行为


那么,为什么说使用RR隔离,我们不会遇到第二次丢失更新的问题呢

我用MySQL做了上面的实验,看起来MySQL实现了一个不同的RR概念:

你可以推断,在这个测试中使用的MySQL版本中,的实现并不像你在另一个问题中说的那样真正符合可重复读取的要求,因为如果你已经这样做了

事务t2从行r1读取相同的数据

再次在步骤4中,而不是

t2修改在#2中读取的数据,并将数据提交给r1

然后t2将读取步骤3中t1保存的值。 因此,您一开始没有可重复读取,因此这不是更新丢失时可重复读取的情况

ANSI SQL-92根据以下现象定义隔离级别:脏 读取、不可重复读取和幻影

而不是像你一开始想的那样用锁

现在,据我所知,RR使用共享读锁和独占写锁 锁

这是因为

ANSI SQL隔离设计人员寻求一个允许许多 不同的实现,而不仅仅是锁定

事实上,这方面的一个例子是

如果READ_COMMITTED_SNAPSHOT设置为OFF(默认设置),则数据库 引擎使用共享锁防止其他事务修改 当前事务运行读取操作时的行。[……]

如果READ_COMMITTED_SNAPSHOT设置为ON,则数据库引擎将使用row 版本控制,以使用事务一致的 在语句开头存在的数据的快照。 锁不用于保护数据不被其他人更新 事务处理

丢失的更新不是这种现象之一,但Argeman在中指出,可重复读取保证没有丢失的更新:

P1=不可重复读取 P4=丢失的更新 P2的松散解释(指定了可能导致 对于异常情况)是

P2(指定实际异常)的严格解释称为A1

A2: r1[x]...w2[x]...c2...r1[x]...c1
而对丢失的更新的解释是

P4: r1[x]...w2[x]...w1[x]...c1
您提出的案例形式如下:

A4: r1[x]...r2[x]...w1[x]...c1...w2[x]...c2
起初,这似乎是一种没有不可重复读取的情况,事实上,t1总是在整个事务中读取相同的x值

但是如果我们关注t2并反转数字,我们可以看到这显然是不可重复读取的情况

A4:r1[x]…r2[x]…w1[x]…c1…w2[x]…c2

A4:r1[x]…w2[x]…c2…w1[x]…c1(为更好的可读性,数字颠倒)

P2:r1[x]…w2[x]…(c1或a1)和(c2或a2)以任何顺序)

A4: r1[x]...r2[x]...w1[x]...c1...w2[x]...c2