八、并发控制
1.并发操作带来的不一致性有哪些?
1.1 丢失修改
两个事务T1和T2读入同一数据并修改,T2提交的结果破坏了T1提交的结果,导致了T1的修改失效了。飞机订票的例子就属于此类。
1.2 脏读
读"脏"数据是指当事务T1修改某一数据时,事务T2读取同一数据后,T1由于某种原因撤销修改了,这时T1已修改过的数据恢复原值,而T2读到的数据是撤销修改之前的数据,那么此时T2的数据就与数据库中的数据不一致,则T2读到的数据就为"脏"数据,即不正确的数据。
1.3 不可重复读
不可重复读是指事务T1读取数据后,事务T2执行更新操作,使T1无法再现前一次读取结果。具体的,不可重复读包括三种情况:
(1)事务T1读取某一数据后,事务T2对其做了修改,当事务1再次读该数据时,得到与前一次不同的值。例如,T1读取B=100进行运算,T2读取同一数据B,对其进行修改后将B=200写回数据库。T1为了对读取值校对重读B,B已为200,与第一次读取值不一致。
(2)事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录神密地消失了。
(2)事务T1按一定条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录。
2.并发控制的主要技术
- 封锁、
- 时间戳
- 乐观控制法
- 多版本并发控制
3.封锁协议
封锁:排他锁(X锁)、共享锁(S锁)
一级封锁协议:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放(防止丢失修改)
二级封锁协议:在一级封锁协议基础上,事务T在读数据R之前先对其加S锁,读完之后释放(防止丢失修改和读脏数据)
三级封锁协议:在一级封锁协议的基础上,事务T在读数据R前先对其加S锁,直到事务完成才释放(防止丢失修改,读脏数据,不可重复读)
4.预防死锁的方法
- 一次封锁法:事务必须一次性将所要用到的数据加锁
缺点:降低了系统的并发度,很难确定要封锁的数据对象
- 顺序封锁法:所有事务按一定的封锁顺序对数据对象实行封锁
缺点:数据不断变化,很难确定一个固定顺序,成本极高
5.死锁的诊断与解除
- 超时法:一个事务的等待时间超过了规定的时限,就认为发生了死锁
缺点:可能误判死锁,时限若设置太长,不能及时发现死锁
- 等待图法:图中有回路代表发生死锁
死锁处理:选择一个处理代价最小的事务将其撤销,释放其持有的所有锁
6.可串行化调度
一个调度S在保证冲突操作的次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个调度S’,如果S’是串行的,称调度S为冲突可串行化的调度。
冲突操作:不同事务对相同数据的读写和写写
不同事务的冲突操作和同一事务的两个操作不可交换
7.两段锁协议
两段锁协议:事务在第一阶段获得封锁,在第二阶段释放封锁,但不能获得封锁
并发执行的所有事务遵守两段锁协议,则这些事务的任何并发调度策略都是可串行化的
遵守两段锁协议的事务可能发生死锁
Slock(B)
R(B)
Slock(A)
Xlock(A) R(A)
wait…… Xlock(B)
wait……
串行的,称调度S为冲突可串行化的调度。
冲突操作:不同事务对相同数据的读写和写写
不同事务的冲突操作和同一事务的两个操作不可交换
[外链图片转存中…(img-aM7uBa33-1699515077374)]
7.两段锁协议
两段锁协议:事务在第一阶段获得封锁,在第二阶段释放封锁,但不能获得封锁
并发执行的所有事务遵守两段锁协议,则这些事务的任何并发调度策略都是可串行化的
遵守两段锁协议的事务可能发生死锁
Slock(B)
R(B)
Slock(A)
Xlock(A) R(A)
wait…… Xlock(B)
wait……