Wiki说;
可重复读取:
在此隔离级别中,基于锁的并发控制DBMS实现将保持读写锁(在选定数据上获取),直到事务结束。但是,范围锁不是托管的,因此可能会发生幻象读取。
在这种隔离级别上可能存在写偏差,这是一种现象,其中两个不同的写入器(他们之前已经读取了它们正在更新的列)允许对表中的同一列进行两次写入,从而导致该列具有两个事务的混合数据。
我很好奇为什么Repeatable reads
中会发生write skew
?它说它将保持读写锁,直到事务结束,当previously read the columns they are updating
时发生write skew
,那么当读锁被锁定时,如何锁定写锁呢?
发布于 2018-09-09 23:14:43
可重复读隔离级别保证每个事务将从数据库的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;
使用更严格的隔离级别的
https://stackoverflow.com/questions/48417632
复制相似问题