目录
什么是封锁
封锁就是事务T在对某个数据对象操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象。一个事务对某个数据对象加锁后究竟拥有什么样的控制由封锁的类型决定。
锁类型
排他锁(X锁)
若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。
共享锁(S锁)
若事务T数据对象A加上S锁,则事务T可以读A但不能修改A,其它事务只能再对A加S锁,而不能加X锁,直到释放A上的锁。保证其它事务可以的读A,但在T释放A上的S锁之前不能对A做任何修改。
锁的相容矩阵
什么是封锁协议
在运用X锁和S锁对数据对象加锁时,需要约定一些规则,这些规则为封锁协议(Locking Protocol)
- 何时申请X锁和S锁
- 持续时间
- 何时释放
一级封锁协议
事务T在修改数据R之前先对其加X锁,直到事务结束才释放。结束分为正常结束COMMIT,非正常结束ROLLBACK。
一级封锁协议可以避免丢失修改,当T2请求修改数据时,由于T1在原数据上增加了X排它锁,锁的相容性不允许对施加了X排它锁的数据对象再请求加锁,故T2的请求加锁只能等待。
在一级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证可重复读和不读“脏”数据。
二级封锁
一级封锁不能解决“不可重复读”和“读脏数据。
二级封锁协议,在一级封锁协议基础上,读取数据时要对其加S锁,读取后即可释放S锁。
二级封锁协议可以防止丢失更新和读“脏”数据。
二级封锁协议不能解决不可重复读问题,因为在二级封锁协议当中S锁是短锁(读取完立即释放)。
1. 1时刻T1读取数据对象A数据对象B,对其请求加S锁。当同时刻事务T2要修改数据对象B,请求加X锁,但是由于锁的相容性,被拒绝,T2事务等待。
2.2时刻T1事务读取完数据对象A和B以后,立即释放S锁,计算得到值为150,但是注意,此时,T1事务还没有完成运行。在T1释放数据对象A和B上的S锁的同时,事务T2便可以对其请求加X锁,修改数据对象A或B,并提交T2事务保存数据变更。并释放X锁。
3. 3时刻,由于事务T1并没有结束,需要再次读取数据对象A和B,那么此时因为T2事务释放了X锁,那么T1事务就能够再次对数据对象A和B请求加S锁,那么T1事务再次读取得到的数据对象是经过T2事务修改得到的,故运算结果与第一次运算150不相同。称为“不可重复读”。
可见二级封锁协议并不能解决不可重复读问题。
三级封锁协议
一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放锁。三级封锁协议可防止丢失更新、读脏数据和不可重复读。
三级封锁协议,和二级封锁协议最重要的区别就在于三级封锁协议的封锁是持续到整个事务结束才释放。那么T1事务在第一次获取数据对象A和B的S锁,以读取数据时,S锁便保留至到T1事务结束才能释放。
那么在T1事务运行期间,如果T2事务想要修改数据对象A和B,请求加X锁,由于此时T1事务加的S锁并没有释放(因为三级封锁协议,锁保留至事务结束),那么锁的相容性并不允许S锁上加X锁,那么T2事务的修改只能等待。等到T1事务结束,那么T2事务才能加X锁进行修改,从而避免了不可重复读。