第8章 并发控制
死锁的诊断与解除 诊断:DBMS一般使用超时法或事务等待图法。 解除:死锁发生后DBMS选择处理代价最小的事务将其回滚,并 释放它所持有的所有锁。
16
3.3.3.5 并发调度的可串行性
可串行化调度:若多个事务并发调度的结果与任一串行调度的 结果相同,则该并发调度是可串行化调度,两段锁协议是保证 并发调度可串行性的封锁协议。 对于一个给定的并发调度,当且仅当它是可串行化的,才认为 是正确的调度。例:设A、B的初值都是2,现有两个事务: 事务T1:读B;A=B+1;写回A。 事务T2:读A;B=A+1;写回B。
并发操作:多个用户同时对某个数据库对象进行的操作。若对 并发操作不加控制就可能存取不正确数据,破坏数据库的一致 性。所以DBMS必须提供并发控制机制,对并发操作进行正确 调度、保证事务的隔离性、保证数据库的一致性,它是衡量一 个DBMS性能的重要标志之一。
3
并发操作可能引起的三类数据不一致问题 丢失修改:指两个事务T1和T2从数据库中读入同一数据并修 改,T2的提交结果破坏了T1提交的结果,导致T1的修改被丢失
事务遵守2PL协议
2 3 4
事务不遵守2PL协议
5
6
A=B+1=3
写回A=3 Commit …… ……
6
7 8 9 10 11
写回A=3
Commit Unlock(A,B)
……
…… …… Slock(A) 读A=3 Xlock(B)
7 8
9
10 11 12 13
Unlock(A)
……
Slock(A) 读A=3 Unlock(A) Xlock(B)
数据库基础与应用
第三章 关系数据库规划和设计(继)
----并发控制
1
学习目标
理解三类数据不一致问题 理解封锁的概念和三级封锁协议 理解活锁和死锁 掌握并发调度的可串行性 掌握2PL协议 理解封锁的粒度 掌握SQL Server的并发控制技术
2
3.3.3.1 并发控制概述
数据库是一个共享资源,允许多个用户同时访问。多用户数据 库系统中多事务的执行方式有:
时间 1 2 3 4 5 6 A=A-1 写回A=15 Commit A=A-1 15 事务T1 读A=16 读A=16 最后的结果错误!原 因是T2执行第7步后丢 失了T1对A的更新。 事务T2 数据库中A的值 16
7
8
写回A=15
Commit
4
15
不可重复读:不可重复读是指事务T1读取数据后,事务T2执 行更新操作,使T1无法再现前一次读取结果。
T1 T2
X锁 S锁 -
X锁 N N Y
S锁 N Y Y
8
- Y Y Y
X锁和S锁的相容性 Y为相容,N为不相容。 若两个锁不相容,则后提 出锁请求的事务必须等待
3.3.3.3 封锁协议
封锁协议:事务对数据封锁时,何时申请X锁或S锁、持锁时间 、何时释放等有关封锁的规则。 一级封锁协议:事务T在修改数据A之前必须先对其加X锁,直 到该事务结束才释放X锁。 (防丢失修改)
……
5
6 7 8 9 10 11 12 13
写回A=15
Commit Unlock(A)
一级封锁协议解决了丢失修改。 …… 但如果T2首先读A,T1修改A(减 1)提交后,T2再读A则出现不可 …… 重复读问题;如果T2在第5步后 Xlock (A) 读A,然后T1执行Rollback,则 14 读A=15 T2读了“脏”数据。
6
读“脏”数据:事务T1修改某一数据,并将其写回磁盘,事 务T2读取同一数据后,T1由于某种原因被撤消,这时事务1已修 改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致 ,则T2读到的数据称为“脏”数据。
时间 1 2 3 事务T1 读C=100 C=C*2 写回C=200 200 最后的结果错误!原因是 T1在第6步取消了对C的更 新,但T2仍使用取消前的 C值,读了“脏”数据。 100
在释放一个封锁之后,事务不再申请和获得任何其他封锁。
两段的含义
扩展阶段:只获得锁,不释放锁。 收缩阶段:只释放锁,不获得锁。 遵守2PL协议是可串行化调度的充分条件,但不是必要条件。
20
遵守及不遵守2PL并发调度示例
时间 1 2 3 4 5 事务T1 Slock(B) 读B=2 Xlock(A) A=B+1=3 Slock(A)等待 事务T2 时间 1 事务T1 Slock(B) 读B=2 Unlock(B) Xlock(A) Slock(A)等待 事务T2
时间 事务T1 事务T2 数据库中A、B的值
1
2 3 4 5
读A=50,B=100
求和150 读B=100 B=B*2 写回B=200
50、100
50、200
6
7 8 9
读A=50,B=200
求和250 Commit
Commit T1无法再现第2步读到 的结果!原因是T2在 第5步对B的修改。
5
不可重复读包括三种情况: 事务T1读取某一数据后,事务T2对其做了修改,当T1再次读 该数据时,得到与前一次不同的值。 事务T1按一定条件从数据库中读取了某些数据记录后,事务T2 删除了其中部分记录,当T1再次按相同条件读取数据时,发现 某些记录神密地消失了。 事务T1按一定条件从数据库中读取了某些数据记录后,事务T2 插入了一些记录,当T1再次按相同条件读取数据时,发现多了 一些记录。 后两种情况也称为幻影现象(Phantom Row)。
17
串行调度
时间 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 事务T1 Slock(B) 读B=2 Unlock(B) Xlock(A) A=B+1=3 写回A=3 Commit Unlock(A) Slock(A) 读A=3 Unlock(A) 事务T2 时间 1 2 3 4 5 6 7 8 9 10 11 Xlock(B) B=A+1=4 写回B=4 Commit Unlock(B)
12
13 14 15
B=A+1=4
写回B=4 Commit Unlock(A,B)
21
14
15 16 17
B=A+1=4
写回B=4 Commit Unlock(B)
2PL协议不同于一次性封锁:一次性封锁遵守2PL协议,但 遵守2PL协议的事务可能发生死锁。
时间
1 2
事务T1
Slock(B) 读B=2
串行执行:每个时刻只有一个事务运行,其他事务必须等到该 事务结束后才能运行,它不能发挥数据库共享资源的特点。
交叉并发方式:事务并行操作,轮流交叉运行,这是单处理机 系统的并发方式,能够减少CPU空闲时间,提高系统的效率。 同时并发方式:多处理机系统中,每个处理机可以运行一个事 务,多个处理机可以同时运行多个事务,实现多个事务真正的 并行运行。这是最理想的并发方式,但受制于硬件环境。
10
11
Commit
Unlock(C)
11
三级封锁协议的并发调度
时间 1 事务T1 Slock (A,B) 事务T2 数据库中A、B的值 50、100
2
3 4 5 6 7
读A=50,B=100
求和150 Xlock(B)等待 读A=50,B=100 求和150 Commit
…… ……
……
三级封锁协议解决了丢失 修改、不可重复读和读“ 脏”数据问题。
时间
1 2 3
事务T1
Xlock(A) Xlock(B)等待 ……
事务T2
Xlock(B) Xlock(A)等待 ……
4
死锁的预防 一次封锁法:要求每个事务必须一次将所有要使用的数据全 部加锁,否则就不能继续执行。它存在两个问题:一是扩大了封 锁范围;二是很难事先精确确定每个事务所要封锁的数据对象, 只能将事务执行中可能要封锁的数据对象全部加锁,降低了并发 度
Unlockቤተ መጻሕፍቲ ባይዱA)
可串行化调度与不可串行化调度
结果A=3、B=4,是可串行化调度
时间
1 2 3 4 5 6
事务T1
Slock(B) 读B=2 Unlock(B) Xlock(A) A=B+1=3 写回A=3
事务T2
Slock(A) 读A=2 Unlock(A) Xlock(B) B=A+1=3 写回B=3
15
顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务都 按这个顺序实行封锁。它也存在两个问题:一是数据库系统中 可封锁的数据对象极多并且不断变化,要维护这些资源的封锁 顺序非常困难;二是事务的封锁请求可以随着事务的执行而动 态地决定,很难事先确定每一个事务要封锁哪些对象,也就很 难按规定的顺序去施加封锁。如规定数据对象的封锁顺序为 A,B,C,D,E。事务T3起初要求封锁数据对象B,C,E,但当它封 锁了B,C后,才发现还需要封锁A,这样就破坏了封锁顺序。 因此DBMS解决死锁更普遍采用诊断+解除的方法。
事务T2
3
4 5 6 7
Xlock(A)等待
……
Slock(A)
读A=2 Xlock(B)等待 ……
二级封锁协议:一级封锁协议加上事务T在读取数据A前必须先 对其加S锁,读完后立即释放S锁(防丢失修改,防读“脏”数 据)。
三级封锁协议:一级封锁协议加上事务T在读取数据A前必须先 对其加S锁,直到该事务结束才释放S锁(防丢失修改,防读“ 脏”数据,防不可重复读)。
9
一级封锁协议的并发调度
时间 1 2 3 4 A=A-1 事务T1 Xlock (A) 读A=16 Xlock (A)等待 事务T2 数据库中A的值 16
4
5 6 7 8 …