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

时间:2012-01-30 06:58:27

标签: hibernate updates isolation

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

1)事务t1从行r1

读取数据

2)事务t2从行r1

读取相同的数据

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

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

我尝试使用Hibernate(隔离级别设置为RR)并看到上面提到的行为。

为什么然后它说RR隔离我们没有第二次丢失更新问题?

2 个答案:

答案 0 :(得分:3)

您可以推断出您在此测试中使用的MySQL版本中的,实现并不真正符合可重复读取,就像您在其他人中所说的那样问题,因为如果你已经完成了

  

事务t2从行r1

读取相同的数据

再次在步骤4中而不是

  

t2修改#2中读取的数据并将数据提交到r1。

然后t2会在步骤3中读取t1保存的值。 因此,您最初没有可重复读取,因此不会出现可重复读取且丢失更新的情况。

  

ANSI SQL-92根据现象定义隔离级别:脏   读取,不可重复读取和幻像。

而不是像你最初想象的那样锁when you said

  

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

这是因为

  

ANSI SQL隔离设计者寻求一种可以承认许多人的定义   不同的实现,而不仅仅是锁定。

事实上,其中一个例子是READ_COMMITED implementation from SQL SERVER

  

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

     

如果READ_COMMITTED_SNAPSHOT设置为ON,则数据库引擎使用行   版本控制以使事务一致性呈现每个语句   在语句开头存在的数据快照。   锁定不用于保护数据免受其他人的更新   交易

丢失的更新不是这种现象之一,但在A Critique of ANSI SQL Isolation Levels中,Argeman在the other question中指出,可重复读取保证不会丢失更新:

P1 =不可重复读取 P4 =丢失更新 对P2的松散解释(指出了可能导致的现象) <异常)是

P2: r1[x]...w2[x]...((c1 or a1) and (c2 or a2) in any order)

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)任何顺序)< / p>

答案 1 :(得分:0)

我曾尝试使用MySQL进行上述实验,看起来MySQL实现了不同的RR概念:MySQL repeatable read and lost update/phantom reads