死锁与活锁
和操作系统一样,封锁的方法可能引起活锁和死锁
活锁
如果事务T1封锁数据D,事务T2又请求封锁数据D,于是T2等待。事务T3也请求封锁D,当T1释放D上的封锁之后系统首先批准了T3的请求,T2又等待,然后T4又请求封锁D。。。T2永远等待
避免活锁的简单方法就是采用先来先服务的策略
死锁
事务T1封锁了数据D1,T2封锁了数据D2,然后T1又请求封锁D2,因为T2已封锁了D1,于是T1等待T2释放D2,接着T2请求封锁D1,T1已封锁了D1,T2等待T1释放D1。T1、T2相互等待,产生死锁。
死锁的预防:
1)一次封锁法:一次封锁法要求事务必须一次将所有要使用的数据全部加锁。
缺点:降低了系统并发行
2)顺序封锁法:顺序封锁法是预先对数据对象规定一个封锁顺序,所有的事务都按照这个顺序实行封锁。
缺点:维护困难,成本高,很难按照规定的顺序实行封锁。
死锁的诊断与解除
1)超时法:如果一个事务的等待时间超过了默认的时间,就认为是产生了死锁。
2)等待图法:一旦检测到系统中存在死锁就要设法解除。通常的解决方法是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,恢复其所执行的数据修改操作,使得其他事务得以运行下去。
两段锁协议
所谓的二段锁协议是指所有事务必须分两个阶段对数据进行加锁和解锁操作。
1)在对任何数据进行读、写操作之前,首先要申请并获得该数据的封锁。
2)在释放一个封锁之后,事务不在申请和获得其他封锁。
也就是说事务分为两个阶段。第一个阶段是获得封锁,也称为扩展阶段。在这个阶段,事务可以申请获得任何数据项任何类型的锁,但是不能释放任何锁。第二阶段是释放封锁,也称为收缩阶段。在这个阶段,事务可以释放任何数据项上任何类型的封锁,但是不能再申请任何锁。
事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件。也就是说遵守两段锁协议一定是可串行化调度的,而可串行化调度的不一定是遵守两段锁协议的。