并发控制

参考:王珊《数据库系统概论》

数据库是一个共享资源,可以供多个用户使用。如果事务串行执行,则许多系统资源将处于空闲状态,因此为了充分利用系统资源,发挥数据库共享资源的特点,应该允许多个事务并行执行。

当多个用户并发的存取数据库时就会产生多个事务同时存取同一事务的情况。因此数据库管理系统要提供并发控制机制,防止破坏事务的一致性和数据库的一致性。

并发控制概述

事务是并发控制的基本单位

为保证事务的隔离性和一致性,数据库系统需要对并发操作进行正确的调度

例如:一个并发操作带来的数据不一致性的问题
并发控制
并发操作带来的数据不一致性包括丢失修改、不可重复读、读“脏”数据

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

2、不可重复读
事务T1读取数据后,事务T2执行更新操作,使T1无法再现前一次读取的结果。包括三种情况:
(1)事务T1读取数据后,事务T2对其进行修改,当事务T1再次读该数据时,得到与前一次不同的值。
(2)事务T2删除了其中部分记录,事务T1再次读取时,发现某些记录神秘的消失了
(3)事务T2插入了一些记录,T1再次读取时,发现多了一些记录

3、读“脏”数据
事务T1修改某一数据后将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤销,这时T1修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据就为“脏”数据,即不正确的数据
并发控制
产生上述三种数据不一致的主要原因是并发操作破坏了事务的隔离性。
并发控制机制就是要用正确的方式调度并发操作,使一个用户事务的执行不受其他事务的干扰,从而避免造成数据的不一致性

并发控制的主要技术:

  • *
  • 时间戳
  • 乐观控制法
  • 多版本并发控制MVCC

*

事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该对象进行操作,在事务T释放它的锁之前,其他事务不能更新此数据对象。

  • 排他锁(X锁、写锁):若事务T对数据对象A加上X锁,则只允许事务T读取和修改A,其他任何事务都不能在对A加任何类型的锁,直到T释放A上的锁为止。保证了其他事务不能读取和修改A。
  • 共享锁(S锁、读锁):若事务T对数据对象A加上S锁,事务T可以读取A但不能修改A,其他事务只能在对A加S锁,不能加X锁,直到T释放A上的S锁为止。这就保证了其他事务可以读A,但是不能对A做任何修改

*协议

在运用X锁和S锁时,还需要约定一些规则,例如何时申请X锁或S锁、持锁时间、何时释放等。这些规则称为*协议。

一级*协议

事务T在修改数据R之前必须对其加X锁,直到事务结束才释放。
可**防止丢失修改**,并不在事务T是可恢复的。

二级*协议

在一级*协议的基础上增加事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。
不仅防止丢失修改,进一步防止读“脏”数据

三级*协议

在一级*协议的基础上增加事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放
不仅防止丢失修改和读”脏“数据,还防止不可重复读
并发控制

活锁和死锁

活锁——先来先服务策略

当多个事务请求*同一数据对象时,*子系统按请求*的先后次序对事务排队,数据对象上的锁一旦释放就批准申请队列中的第一个事务获得锁。

死锁

两个或两个以上的事务都已*了一些数据对象,然后又都请求对已被其他事务*的数据对象加锁,从而出现死等待。解决方法有两种:
1、预防死锁的发生(不太适合)

  • 一次*法:要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。
  • 顺序*法:预先对数据对象规定一个*顺序,所有事务都按这个顺序实施*

2、死锁诊断并解除

诊断方法:等待图法、超时法

解除方法:选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有锁,使其他事务得以继续运行下去。

并发调度的可串行性

并发控制机制调度并发事件是否正确的判别准则是可串行性,两段锁协议是可串行化调度的充分条件,但不是必要条件。因此,两段锁协议可以保证并发事务调度的正确性。

时间戳方法

给每个事务盖上一个时标,即事务开始执行的时间。每个事务具有唯一的时间戳,并按照这个时间戳来解决事务的冲突操作

乐观控制法

多版本并发控制

数据库中通过维护 数据对象的多个版本信息来实现高效并发控制
版本:数据库中数据对象的一个快照,记录了数据对象某个时刻的状态。