1、解锁与死锁问题
��如果对数据项进行读写之后立即解锁,容易造成数据库的不一致,那么是否把解锁的时机往后推到事务的末尾就万事大吉了呢?图11-1-4给我们展示了不立即解锁又可能造成的死锁问题。但是死锁还是要比造成数据库不一致要好,因为死锁可以通过DBMS回滚某事务加以解决,而数据库的不一致,则必须通过程序员或DBA执行一个补偿事务才可以恢复数据库的一致性(参阅第十章"事务"的10.2.1小节)。

图11-1-4:一个死锁的调度
为什么图11-1-4中的调度会产生死锁呢?因为事务T3一开始就申请了数据项B上的排他锁,接着事务T4申请了数据项A上的共享锁;在事务T4申请数据项B上的共享锁时,由于事务T3持有数据项B上的排他锁,因此事务T4不能立即得到该锁,只能等待事务T3释放锁;接下来事务T3申请数据项A上的排他锁,由于此时事务T4持有数据项A上的共享锁,因此事务T3不能立即得到该锁,只能等待事务T4释放锁。这就造成了两个事务互相等待的死锁现象。
2、饿死问题
��在基本的封锁协议中,锁的授予条件是:当事务申请对某数据项加某类型锁,并且没有其他事务在该数据项上加有与该事务所申请的锁不相容的锁时,则并发控制管理器可以授予锁。但这种宽松的锁授予条件容易产生另外一个我们俗称为饿死的问题,如图11-1-5所示:
图11-1-5:具有饿死现象的调度
图11-1-5中,首先是事务T6申请数据项Q上的共享锁,紧接着事务T5申请数据项Q上的排他锁,因与事务T6持有的共享锁冲突,因此事务T5只能等待事务T6释放锁;而在事务T6释放锁之前,事务T7又成功申请到数据项Q上的共享锁,因此事务T5又不得不等待事务T7释放锁。这样一直持续下去,事务T5将永远只能处于等待状态,不能得到锁。这种现象就是所谓的饿死问题。





��综上所述,我们必须重新考虑基本的封锁协议中并发控制管理器授权加锁的条件:当事务Ti申请对数据项Q加M型锁时,授权加锁的条件是:
��①�不存在在数据项Q上持有与M型锁冲突的锁的其他事务;
��②�不存在等待对数据项Q加锁且先于Ti申请加锁的其他事务。