Wiki说;
可重复阅读:
在这个隔离级别,基于锁定 并发控制DBMS实现保持读写锁 (根据所选数据获得)直到交易结束。然而, 范围锁不受管理,因此可以进行幻像读取。在此隔离级别可能会出现写入偏斜,这是一种现象,即两种情况 写入允许两个不同的表中的相同列 作者(以前读过他们正在更新的专栏), 导致列具有两者混合的数据 交易。
我很好奇为什么write skew
Repeatable reads
会发生?
它说它将保持读取和写入锁定直到事务结束,而write skew
发生在previously read the columns they are updating
时,那么当读取锁被锁定时如何锁定写锁定?
答案 0 :(得分:10)
可重复的读取隔离级别确保每个事务将从数据库consistent snapshot中读取。换句话说,在同一事务中两次被检索的行始终具有相似的值。
可重复读取隔离级别的某些数据库(例如Postgres,SQLServer)可以检测到lost update(写偏斜的特殊情况),而另一些则不能。 (即:MySQL中的InnoDB)
回写偏斜问题。在某些情况下,大多数数据库引擎无法以可重复的读取隔离检测到。一种情况是 2个并发事务修改了 2个不同的对象并产生竞争条件。
我以Designing Data-Intensive Application为例。这是场景:
您正在为医生编写应用程序以管理他们的待命 在医院轮班。医院通常会尝试几个 任何时候都应召集医生,但绝对必须至少有 一位医生在召唤。医生可以放弃轮班(例如,如果他们 自己生病),但至少要有一名同事留在 接班
那么我们如何在数据库下实现它。这是伪代码sql代码:
BEGIN TRANSACTION;
SELECT * FROM doctors
WHERE on_call = true
AND shift_id = 1234;
if (current_on_call >= 2) {
UPDATE doctors
SET on_call = false WHERE name = 'Alice' AND shift_id = 1234;
}
COMMIT;
如上图所示,我们看到Bob和Alice同时在SQL代码之上运行。但是Bob和Alice修改了不同的数据,Bob修改了Bob的记录,而Alice修改了Alice的记录。数据库处于可重复读取隔离级别,无法理解和检查条件(总医生> = 2)是否已被违反。写偏斜发生了。
要解决此问题,有两种方法:
这里是使用SELECT .. FOR UPDATE
查询的伪代码。
BEGIN TRANSACTION;
SELECT * FROM doctors
WHERE on_call = true
AND shift_id = 1234 FOR UPDATE; // important here: locks all records that satisfied requirements.
if (current_on_call >= 2) {
UPDATE doctors
SET on_call = false WHERE name = 'Alice' AND shift_id = 1234;
}
COMMIT;