学习笔记——DB并发控制

        在单处理机系统中, 事务的并行执行实际上是这些并行事务的并行操作轮流交叉运行。称为交叉并发方式(interleaved concurrency)。虽然单处理机系统中的并行事务并没有真正地并行运行, 但是减少了处理机的空闲时间, 提高了系统的效率。

一、概述

       事务是并发控制的基本单位, 保证事务的ACID特性是事务处理的重要任务, 而事务的ACID特性可能遭到破坏的原因之一是多个事务对数据库的并发操作造成的。 为了保证事务的隔离性和一致性, DBMS需要对并发操作进行正确调度。 这些就是数据库管理系统中并发控制机制的责任。
       并发操作带来的数据不一致性包括丢失修改、不可重复读和读“脏”数据。

       1)丢失修改:两个事务T1和T2读入同一数据并修改,T2提交的结果破坏了T1提交的结果,导致T1的修改被丢失。

       2)不可重复读:指事务T1读取数据后,事务T2执行更新操作,使T1无法再现前一次读取结果。

       3)读“脏”数据:指事务T1修改某一数据并将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤销,这时被T1修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据就为“脏”数据,即不正确的数据。

       产生上述三类数据不一致性的主要原因是并发操作破坏了事务的隔离性。并发控制机制就是要用正确的方式调度并发操作,使一个用户事务的执行不受其他事务的干扰,从而避免造成数据的不一致性。

       并发控制的主要技术有封锁(locking)、时间戳(timestamp)、乐观控制法(optimistic scheduler)和多版本并发控制(multi-version concurrency control,MVCC)等。

二、封锁

       所谓封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其他事务不能更新此数据对象。

       确切的控制由封锁的类型决定。基本类型:排他锁(exclusive locks,简称X锁)和共享锁(share locks,简称S锁)。

       排他锁又称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A, 其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁为止。这就保证了其他事务在T释放A上的锁之前不能再读取和修改A。

       共享锁又称为读锁。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁为止。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

相容矩阵:

三、封锁协议

       在运用X锁和S锁这两种基本封锁对数据对象加锁时, 还需要约定一些规则。如:何时申请X锁或S锁、 持锁时间、 何时释放等。 这些规则称为封锁协议(locking protocol)。对封锁方式制定不同的规则, 就形成了各种不同的封锁协议。

      一级封锁协议是指,事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。一级封锁协议可防止丢失修改,并保证事务T是可恢复的。在一级封锁协议中,如果仅仅是读数据而不对其进行修改,是不需要加锁的,所以它不能保证可重复读和不读“脏”数据。

       二级封锁协议是指,在一级封锁协议基础上增加事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。二级封锁协议除防止了丢失修改,还可进一步防止读“脏”数据。在二级封锁协议中,由于读完数据后即可释放S锁,所以它不能保证可重复读。

       三级封锁协议是指,在一级封锁协议的基础上增加事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。三级封锁协议除了防止丢失修改和读“脏”数据外,还进一步防止了不可重复读。

不同级别的封锁协议和一致性保证:

四、活锁和死锁

(1)活锁:如果事务T1封锁了数据R,事务T2又请求封锁R,于是T2等待;T3也请求封锁R,当T1释放了 R上的封锁之后系统首先批准了 T3的请求,T2仍然等待;然后T4又请求封锁 R,当T3释放了R上的封锁之后系统又批准了T4的请求……T2有可能永远等待。

       避免活锁:采用先来先服务的策略。当多个事务请求封锁同一数据对象时,封锁子系统按请求封锁的先后次序对事务排队,数据对象上的锁一旦释放就批准申请队列中第一个事务获得锁。

(2)死锁:如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2已封锁了R2,于是T1等待T2释放R2上的锁;接着T2又申请封锁R1,因T1已封锁了 R1,T2等待T1释放R1上的锁。这样就出现了 T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。

       在数据库中解决死锁问题主要有两类方法,一类方法是采取一定措施来预防死锁的发生,另一类方法是允许发生死锁,进行死锁的诊断与解除。

(3)死锁的预防:

       防止死锁的发生其实就是要破坏产生死锁的条件。预防死锁通常有以下两种方法:

       1)一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。

         第一,一次就将以后要用到的全部数据加锁, 势必扩大了封锁的范围, 从而降低了系统的并发度;

         第二, 数据库中数据是不断变化的, 原来不要求封锁的数据在执行过程中可能会变成封锁对象, 所以很难事先精确地确

         定每个事务所要封锁的数据对象, 为此只能扩大封锁范围, 将事务在执行过程中可能要封锁的数据对象全部加锁, 这就

         进一步降低了并发度。

       2)顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实施封锁。

         存在问题,顺序很难确定。

       可见,在操作系统中广为采用的预防死锁的策略并不太适合数据库的特点,因此DBMS在解决死锁的问题上普遍采用的是诊断并解除死锁的方法。一般使用超时法或事务等待图法。

(4)死锁的诊断与解除

超时法:如果一个事务的等待时间超过了规定的时限,就认为发生了死锁。

              超时法实现简单,但存在缺点:一是有可能误判死锁, 如事务因为其他原因而使等待时间超过时限;系统会误认为发

              生了死锁; 二是时限若设置得太长, 死锁发生后不能及时发现。

事务等待图:动态地反映了所有事务的等待情况。并发控制子系统周期性地(比如每隔数秒)生成事务等待图,并进行检测。如果发现图中存在回路,则表示系统中出现了死锁。

                

解除死锁:选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁, 使其他事务得以继续运行下去。当然,对撤销的事务所执行的数据修改操作必须加以恢复。

             

五、可串行化调度

       定义多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务时的结果相同,称这种调度策略为可串行化(serializable)调度。

       为了保证并发调度的正确性,DBMS的并发控制机制必须提供一定的手段来保证调度是可串行化的。目前DBMS普遍采用两段锁(TwoPhase Locking,简称 2PL)协议的方法实现并发调度的可串行性,从而保证调度的正确性。所谓两段锁协议是指所有事务必须分两个阶段对数据项加锁和解锁。

遵循两段锁协议的可串行化调度:

       事务遵守两段锁协议是可串行化调度的充分条件, 而不是必要条件。也就是说, 若并发事务都遵守两段锁协议, 则对这些事务的任何并发调度策略都是可串行化的; 但是, 若并发事务的一个调度是可串行化的, 不一定所有事务都符合两段锁协议。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值