数据库学习笔记——并发控制

数据库学习笔记——并发控制

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

并发操作带来的不一致性包括修改丢失(lost update)、不可重复读(non-repeatable read)、读“脏”数据(dirty row).

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

封锁

基本的封锁有两种类型:排他锁(exclusive locks,X锁)、共享锁(share key,S锁)。

  • 排他锁又称写锁,若事务T对数据对象A加上X锁,则只允许T可以读取和修改A。
  • 共享锁又称读锁,若事务T对数据对象加上S锁,则事务T可以读A但不可以修改A,其他事务只能再对A加S锁。

封锁协议

  • 一级封锁协议:事务T在修改数据R之前必须先对其加X锁,直到事务结束释放
  • 二级封锁协议:在一级封锁协议基础上增加事务T在读取数据R之前必须对其加S锁,读完即可释放S锁。
  • 三级封锁协议:在一级封锁协议的基础上增加事务T在读取数据R之前必须先对其加S锁,直到事务结束释放。
不同协议和一致性保证

活锁和死锁

活锁:多个事务请求封锁R,没有其他策略的情况下,先来的请求可能长时间得不到批准,简单方法就是先来先服务策略。

死锁:事务A先请求资源1,后请求资源2;事务B先请求资源2,后请求资源2,会导致事务A、B都得不到所需的所有资源,导致死锁。

死锁的预防:

  • 一次封锁法:一次性申请全部所需资源
  • 顺序封锁法:所有事务都按照规定好的顺序封锁资源

死锁的诊断和解除:

  • 超时法
  • 等待图法:等待图为有向图,若图中出现了回路则发生了死锁。

一般解决方案为选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有锁,使其他事务运行下去。

并发调度的可串行性

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

冲突操作是指不同的事务对同一数据的读写操作或写写操作。

一个调度Sc在保障冲突操作次序不变的情况下,通过交换两个事务不冲突操作得到另一个调度Sc',如果Sc'是可串行的,称调度Sc为冲突可串行化的调度。

若一个调度是冲突可串行化的,则一定是可串行化的调度。

两段锁协议

  • 在对任何数据进行读、写操作之前,首先要申请并获得对该数据的封锁
  • 在释放一个封锁之后,事务不再申请和获得任何其他封锁

所谓“两段”锁的含义是,事务分为两个阶段,第一阶段是获得封锁,也称为拓展阶段,在这个阶段,事务可以申请获得任何数据项上的任何类型的锁,但是不能释放锁;第二阶段是释放锁,也成为收缩阶段,在这个阶段,事务可以释放任何数据项上的任何类型的锁,但是不能再申请任何锁。

两段锁协议不同于防止死锁的一次封锁法,不需要一次性将所有的数据全部加锁,所以遵守两段锁协议的事务可能发生死锁。

封锁的粒度

封锁对象的大小成为粒度。封锁粒度与系统的并发度和并发控制的开销密切相关。

一个系统同时支持多种封锁粒度供不同事务选择的方法成为多粒度封锁(multiple granularity locking)。

多粒度封锁协议允许多粒度树种的每个节点被独立加锁。对一个节点加锁意味着这个节点的所有后裔节点也被加一样的锁。

显式封锁是应事务要求直接加到数据对象上的锁;

隐式封锁是该数据对象没有被单独加锁,是由于其上级节点加锁而使该数据对象加上了锁。

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

三种常用的意向锁:

  1. 意向共享锁(Intent Share Lock,IS锁)

    如果对一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁。

  2. 意向排他锁(Intent Exclusive Lock,IX锁)

    如果一个数据对象加IX锁,表示它的后裔结点拟加X锁。

  3. 共享意向排他锁(Shared Intent Exclusive Lock,SIX锁)

    如果一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX=S+IX。