数据库事务与并发控制

一、事务

事务的四个特性(ACID特性)

  • 原子性(Atomicity
    事务是一个整体,不可拆分;要么都做,要么都不做
  • 一致性(Consistency
    事务执行结果必须是使数据库从一个一致性状态变到另一个一致性状态;当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。
  • 隔离性(Isolation
    一个事务的执行不能被其他事务干扰
  • 持续性(Durability
    持续性也称永久性(Permanence),指的是事务一旦提交,它对数据库中数据的改变就应该是永久的。

二、数据不一致

1. 丢失修改(lost update

甲售票点和乙售票点同时从数据库中读取到某航班余票为16;
甲售票点卖出一张机票,修改余票为15,写入数据库;
乙售票点也卖出一张机票,修改余票为15,写入数据库;
此时两个售票点卖出了2张票,却只减了1张余票。

2. 不可重复读(non-repeatable read

指的是事务T1读取某一数据后,事务T2执行更新操作,使T1无法再现前一次的读取结果。
①(修改)事务T1读取某一数据后,事务T2对其进行了修改,当事务T1再次读取时,得到与前一次不同的值
②(删除)事务T1读取了一些数据后,事务T2删除了其中一部分数据,T1按相同条件读取时,得到的数据少了
③(新增)事务T1读取了一些数据后,事务T2新增了一些数据,T1按相同条件读取时,得到的数据多了
后两种不可重复读有时也称为幻影(phantom row现象

3. 读脏数据(dirty read

事务T1修改某一数据并将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤销了,这时被T1修改的数据恢复原值,T2读取的数据就是脏数据

三、并发控制技术

封锁(locking)、时间戳(timestamp)、乐观控制法(optimistic scheduler)、 多版本并发控制(multi-version concurrency controll MVCC)...

1. 基本的封锁类型:

  • 排它锁(exclusive locks)又称写锁(X锁
    事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直至T释放A上的锁
  • 共享锁(share locks)又称读锁(S锁
    事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对AS锁,而不能加X锁,直至T释放A上的S锁为止

相容矩阵

Y=Yes,N=No S锁 X锁 -
S锁 Y N Y
X锁 N N Y
- Y Y Y

2. 封锁协议

  • 一级封锁协议
    事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。(事务结束包括rollbackcommit
    一级封锁协议可防止丢失修改
  • 二级封锁协议
    在一级封锁协议的基础上,增加事务T在读取数据R之前必须先对其加S锁,读完后即可释放S
    二级封锁协议除了防止丢失修改,还可进一步防止读脏数据
  • 三级封锁协议
    在一级封锁协议的基础上,增加事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放
    三级封锁协议除了 防止丢失修改和读脏数据,还进一步防止了不可重复读

3. 活锁和死锁

  • 活锁
    事务T1,T2,T3,T4都需要同一资源R,
    首先T1封锁了R,这时T2请求封锁R,T3也请求封锁R;
    当T1释放了资源R时,系统首先批准了T3的请求,T2依旧等待;
    此时T4又请求封锁R,待T3释放R时,系统又将R分配给了T4,T2可能永远等待
    解决方法:先来先服务
  • 死锁
    事务T1封锁了R1,T2封锁了R2;
    然后T1又请求封锁R2,但R2被T2锁定,T1只能处于等待状态。
    这时T2又请求封锁R1,但R1被T1锁定,T2也只能等待
    此时T1等待T2,T2又等待T1
  1. 死锁的预防方法
    一次封锁法:每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。
    顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实施封锁。
  2. 死锁的诊断和解除
    超时法:设置最大等待时间
    等待图法:画出等待图,出现回路则出现了死锁
    解决方法:选择一个处理死锁代价最小的事务,释放其所占用的资源

4. 两段锁协议

为了保证并发调度的正确性,目前数据库管理系统普遍采用两段锁协议(TwoPhase Locking 2PL)来实现并发调度的可串行性,从而保证调度的正确性。

所谓两段锁协议就是指事务必须分两个阶段对数据项进行加锁和解锁:

  • 获得封锁——扩展阶段:事务可以申请获得任何数据项上的任何类型的锁,但是不能释放任何锁
  • 释放封锁——收缩阶段:事务可以释放任何数据项上任何类型的锁,但是不能再申请任何锁

若并发执行的所有事务均遵循两段锁协议,则对这些事务的任何并发调度策略都是可串行化的。

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

事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件

5. 封锁的粒度

封锁对象的大小称为封锁的粒度(granularity)
以关系型数据为例,封锁对象可以是这样一些逻辑单元:属性值、属性值的集合、元祖、关系、索引项、整个索引直至整个数据库;也可以是物理单元:页(数据页或索引页)、物理记录等

封锁粒度与系统的并发度和并发控制的开销密切相关,封锁粒度越大,并发度就越小,系统开销就越小;

在一个系统中同时支持多种封锁粒度供不同的事务选择是比较理想的,这种封锁方法称为多粒度封锁(multiple granularity locking)

多粒度树:多粒度树的根节点是整个数据库,表示最大的数据粒度,叶节点表示最小的数据粒度。多粒度封锁协议允许多粒度树中每个节点被独立地加锁。对一个节点加锁意味着这个节点的所有后裔节点也被加以同样类型的锁。

显示封锁:应事务的要求直接加到数据对象上的锁
隐式封锁:该数据对象没有被独立加锁,由于其上级节点加锁而使该数据对象加上了锁


意向锁

一般地,对某个数据对象加锁,有几个检查步骤:
step 1 :系统检查该数据对象上有无显式封锁与之冲突;
step 2 :再检查其所有上级节点,看本事务的显式封锁是否与该数据对象上的隐式封锁冲突;
step 3 :还要检查所有下级节点,看它们的显式封锁是否与本事务的隐式封锁冲突;
显然,这样的检查效率十分低下,为此,人们引入了一种新型锁,称为意向锁(intention lock)

意向锁的含义是如果对一个节点加意向锁,则说明该节点的下层节点正在被加锁;对任一节点加锁时,必须先对它的上层节点加意向锁。

  • ① 意向共享锁(Intent Share Lock,IS锁
    如果对一个数据对象加IS锁,则表示它的后裔节点意向加S锁
    例如:事务T1要对R1中某个元祖加S锁,则首先要对关系R1和数据库加IS锁
  • ② 意向排它锁(Intent Exclusive Lock,IX锁
    如果对一个数据对象加IX锁,则表示它的后裔节点意向加X锁
    例如:事务T1要对R1中某个元祖加X锁,则要首先对关系R1和数据库加IX锁
  • ③ 共享意向排他锁(Share Intent Exclusive Lock,SIX锁
    如果对一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX = S + IX
    例如:对某个表加SIX锁,则表示该事务要读整个表(所以要对表加S锁),同时会更新个别元祖(所以要加IX锁

申请封锁时应该按自上而下的次序进行,释放封锁时应该按自下而上的次序进行。

相容矩阵(Y=Yes,N=No) S锁 X锁 IS锁 IX锁 SIX锁 -
S锁 Y N Y N N Y
X锁 N N N N N Y
IS锁 Y N Y Y Y Y
IX锁 N N Y Y N Y
SIX锁 N N Y N N Y
- Y Y Y Y Y Y

6. 其他并发控制技术

  • ① 时间戳方法
    时间戳方法给每一个事务盖上一个时标,即事务开始执行的时间。每个事务具有唯一的时间戳,并按照这个时间戳来解决事务的冲突操作。如果发生冲突操作,就回滚具有较早时间戳的事务,以保证其他事务的正常执行,被回滚的事务被赋予新的时间戳并从头开始执行。
  • ② 乐观控制法
    乐观控制法任务事务执行时很少发生冲突,因此不对事务进行特殊的管制,而是让它自由执行,事务提交前再进行正确性检查。如果检查后发现该事务执行过程中出现过冲突并影响了可串行性,则拒绝提交并回滚该事务。乐观控制法又被称为验证方法(certifier)。
  • ③ 多版本并发控制
    版本(version)是指数据库中数据对象的一个快照,记录了数据对象某个时刻的状态。

你可能感兴趣的:(数据库事务与并发控制)