han*_*ora 7 database acid isolation-level
维基说;
可重复读取:
在此隔离级别中,基于锁的并发控制DBMS实现保持读取和写入锁定(在选定数据上获取),直到事务结束.但是,不管理范围锁定,因此可能会发生幻像读取.在这种隔离级别可以进行写入偏移,这种现象是两个不同的写入者(他们之前已经读过他们正在更新的列)允许两个写入表中的同一列,从而导致列具有的数据是这两笔交易的混合.
我很好奇为什么write skew会发生Repeatable reads?它说它将保持读取和写入锁定,直到事务结束并write skew发生时previously read the columns they are updating,因此如何锁定读取锁定时写入锁定?
hqt*_*hqt 13
可重复读取隔离级别可确保每个事务都从数据库的一致快照读取.换句话说,在同一事务中检索两次行总是具有相似的值.
Postgres,SQLServer等可重复读隔离级别的数据库可以检测丢失的更新(写偏斜的特殊情况),但有些则没有.(即:MySQL中的InnoDB)
回来写歪斜问题.在某些情况下,大多数数据库引擎无法在可重复的读隔离中检测到.一种情况是2个并发事务修改2个不同的对象并产生竞争条件.
我以设计数据密集型应用程序为例.这是场景:
您正在为医生编写申请,以管理他们在医院的随叫随到的轮班.医院通常会在任何时候试图让几位医生随叫随到,但绝对必须至少有一位医生随叫随到.医生可以放弃轮班(例如,如果他们自己生病了),前提是至少有一位同事留在那个班次
那么我们如何在数据库下实现这一点.这是伪代码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;
Run Code Online (Sandbox Code Playgroud)
如上图所示,我们看到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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
924 次 |
| 最近记录: |