使用可重复读隔离级别,仍然有可能丢失更新(第二次丢失更新问题)。例如,在隔离级别设置为RR的情况下:
1)事务t1从行r1读取数据,
2)事务t2从行r1读取相同的数据,
3) t1修改#1中读取的数据,并将数据提交给r1
4) t2修改#2中读取的数据并将数据提交给r1。T1的更新丢失
我尝试了Hibernate (隔离级别设置为RR),并看到了上面提到的行为。
那么,为什么说使用RR隔离,我们不会遇到第二次丢失更新的问题?
发布于 2012-04-06 16:36:59
我用MySQL尝试了上面的实验,看起来MySQL实现了一个不同的RR概念:MySQL repeatable read and lost update/phantom reads
发布于 2016-01-17 10:31:59
您可以在此测试中使用的MySQL版本中推断出,正如您在其他问题中所说的那样,实现并不真正符合可重复读取,因为如果您已经这样做了
transaction 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,则数据库引擎使用行版本化来为每个语句提供与语句开头的数据在事务上一致的快照。锁不用于保护数据不受其他事务的更新。
丢失的更新不是这种现象之一,但Argeman在the other question中指出的A Critique of ANSI SQL Isolation Levels中解释说,可重复读取保证不会丢失更新:
P1 =不可重复读取P4 =丢失更新对P2 (指定可能导致异常的现象)的松散解释是
P2: r1[x]...w2[x]...((c1 or a1) and (c2 or a2) in any order)称为A1的P2 (指定实际异常)的严格解释是
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并反转数字,我们可以看到这显然是一个不可重复读取的情况。
r1x...r2x...w1x...c1...w2x...c2:
A4
r1x...w2x...c2...w1x...c1 :A4(为了更好的可读性,将数字颠倒过来)
P2:r1x...w2x...((c1或a1)和(c2或a2)按任意顺序排列)
https://stackoverflow.com/questions/9060400
复制相似问题