1、 数据库原理第 十一章 数据库并发控制数据库是可以共享的资源,即供多个用户使用。允许多个用户同时使用的数据库系统称为多用户数据库系统。为了充分利用系统资源,如 CPU, 内存等,应该允许多个事务并发执行。事务并发执行分为两种:o 交叉并发方式:并行事务的并行操作轮流交叉进行,如单处理机系统中的并行事务o 同时并发方式:在多处理机系统中,可以同时运行多个事务,实现多个事务真正的并行运行 11.1 并发控制概述并发操作可能带来数据的不一致性,包括三种情况: 丢失修改 不可重复读:修改,删除,插入 读 “脏 ”数据产生以上不一致性的主要原因是并发操作破坏了事务的隔离性,并发控制就是要用正确的方式调度
2、并发操作,使事务的执行不会相互干扰。但有时对数据库允许某些不一致性,如有些统计工作涉及数据量很大,这时读一些不正确的数据对统计精度影响不大,这时可以降低一致性的要求以减少系统开销。为了解决以上问题,主要采用的技术是给数据加锁。11.2 封锁一 定义:封锁就是对事务 T在对某个数据对象例如表,记录等操作之前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在事务 T释放它的锁之前,其它的事务不能更新此数据对象。二 类型: 排它锁( X锁):又称为写锁。如果事务 T对数据对象 加上 X锁,则只允许 T读取和修改 A, 其它任何事务都不能 再对 A加任何类型的锁,直到 T释放 A
3、上的锁。这就保证了其它事务在 T释放 A上的锁之前不能再读取和修改 A。 共享锁( S锁):又称读锁。若事务 T对数据对象 A加上S锁,则事务 T可以读取 A但不能修改 A, 其它事务只能对 A加 S锁而不能加 X锁,直到 T释放 A上的 S锁。这就保证了其它事务可以读 A, 但在 T释放 A上的 S锁之前不能修改 A。11.3 封锁协议一 定义对数据加锁时约定的一些规则称为封锁协议。二 分类v 一级封锁协议:事务 T在修改数据 R之前必须对其加 X锁,直到事务结束(包括 COMMIT和 ROLLBACK) 才释放。一级封锁协议可以解决丢失修改。v 二级封锁协议:一级封锁协议加上事务 T在读取
4、数据 R之前必须先对其加 S锁,读完后可立即释放 S锁。二级封锁协议不仅可以解决丢失修改,还可以解决读“脏数据 ”问题。v 三级封锁协议:一级封锁协议加上事务 T在读取数据 R之前必须先对其加 S锁,直到事务结束才释放。三级封锁协议不仅可以解决丢失修改和读 “脏数据 ”问题,还可以防止不可重复读。11.4 活锁和死锁一 活锁如果事务 T1封锁了数据 R, 接着事务 T2也请求封锁 R, 那么 T2只能等待。接着 T3也请求封锁 R, 当 T1释放了 R上的锁之后系统首先批准了 T3的请求, T2只能再次等待。然后 T4也请求封锁 R, 当 T3释放了 R上的锁之后系统又批准了 T4的请求, T
5、2仍然等待。这样 T2有可能永远等待而无法获得对 R加锁的权利,这就是活锁的情况。解决活锁的简单办法就是 “先来先服务 ”。二 死锁如果事务 T1封锁了数据 R1, T2封锁了数据 R2。 然后T1又请求封锁 R2, 但此时 R2已被封锁,于是 T1等待 T2释放 R2上的锁。接着 T2请求封锁 R1, 但此时 R1已被封锁,于是 T2等待 T1释放 R1上的锁。这样就出现了 T1等待 T2,而 T2又在等待 T1的局面, T1和 T2两个事务永远不可能结束,形成死锁。死锁的解决办法有两种:1. 预防 一次封锁法:要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续下去。存在的问题:一次将以后要用到的数据全部加锁,扩大了封锁的范围,从而降低了系统的并发度。 数据库中的数据是不断变化的,很难精确地判断每个事务所要封锁的数据对象,为此只能加大封锁范围,将事务在执行中可能要封锁的对象都加上锁,这就进一步降低了并发度。 顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务都按这个顺序进行封锁。存在的问题:数据库系统的数据对象很多且不断变化,要维护一个特定的封锁顺序很困难。很难预先确定某个事务要封锁哪些对象,因此也就很难按规定的顺序进行封锁了。 在数据库中预防这种方法用得并不多。