一、并发控制概述
事务是并发空值的基本单位,保证事物的ACID特性是事务处理的任务,而事务的ACID特性可能遭到破坏的原因之一是多个事务对数据库的并发操作造成的。因此,为了保证事务的隔离性和一致性,数据库管理系统需要对并发操作进行正确的调度。
并发操作带来的不一致性包括丢失修改、不可重复读和读“脏数据”。
1. 丢失修改
两个事务(T_1)和(T_2)读入同一数据并修改,(T_2)提交的提交结果破坏了(T_1)提交的结果,导致(T_1)的修改被丢失。
2. 不可重复读
不可重复读指事务(T_1)读取数据后,事务(T_2)执行更新操作,使(T_1)提交的结果,导致(T_1)的修改被丢失。
3. 读“脏”数据
事务(T_1)修改某一数据并将其写回磁盘,事务(T_2)读取同一数据后,(T_1)由于某种原因被撤销,这时(T_2)读到的就是“脏数据”。
并发控制机制就是要正确的方式调度并发控制,使一个用户事务的执行不受其他事务的干扰。
并发控制的主要技术有封锁、时间戳、乐观控制法和多版本并发控制等。
二、封锁
1. 排他锁(写锁)
若事务(T)对数据对象(A)加上(X)锁,则只允许(T)读取和修改(A),而其他事务不行,并且其c'c他事务都不能再对(A)加任何类型的锁,直到它被事务(T)释放为止。
2. 共享锁(读锁)
若事务(T)对数据对象(A)加上(S)锁,则事务(T)可以读取(A)但不能修改(A),其他事务只能再对(A)加(S)锁,直到它被事务(T)释放为止。
三、封锁协议
1. 一级封锁协议(防止丢失修改)
事务(T)在修改数据(R)之前必须先对其加(X)锁,直到事务结束才释放。
一级封锁协议可以防止丢失修改。
2. 二级封锁协议(防止读“脏”数据)
二级封锁协议指,在一级封锁协议的基础上增加事务(T)在读取数据(R)之前必须先对其加(S),读完后即释放(S)锁。
二级封锁协议除了可以防止修改丢失,还可以进一步防止读“脏”数据。
3. 三级封锁协议(防止不可重复读)
三级封锁协议指,在一级封锁协议的基础上增加事务(T)在读取数据(R)之前必须先对其加(S)锁,直到事务结束才释放。
三级封锁协议还进一步防止了不可重复读。
四、活锁和死锁
活锁
事务(T)请求封锁数据(R),但是一直被其他事务“插队”,导致(T)永远等待,这就是活锁,即数据(R)一直再被请求与释放,而事务(T)却无法请求到它。
死锁
多个事务相互等待对方封锁的数据,却互不相让,最终这些事务会一直僵持下去,形成死锁。
死锁的预防:
- 一次封锁法:一次将该事务所需要的全部数据一起封锁。
- 顺序封锁法:按规定的顺序对数据进行封锁。
死锁的诊断与解除:
- 超时法
- 等待图法
如果发生死锁,通常来说,数据库管理系统会选择一个处理死锁代价最小的事务,将其撤销,释放该事务持有的所有锁。
五、并发调度的可串行性
数据库管理系统对并发事务不同的调度可能产生不同的结果。其中,串行调度是正确的,执行结果等价于串行调度的调度也是正确的。
1. 可串行化调度
多个事务的并发执行是正确的,当且仅当其结果与按某一次串行地执行这些事务时的结果相同,这种策略就是可串行化调度。
可串行性是并发事务正确调度的准则。只有一个调度可以串行化,其才可能是正确的。
2. 冲突可串行化调度
冲突操作指不同的事务对同一个数据的读操作和写操作;
一个调度(S_c)在保证冲突操作的次序不变的情况下,通过交换两个事务不冲突的操作次序得到另一个调度(S_c'),如果(S_c')是可串行的,称调度(S_c)为冲突可串行化的调度。
若一个调度是冲突可串行化,则一定是可串行化的调度。
冲突可串行化调度是串行化调度的充分条件,不是必要条件。
六、两段锁协议
两段锁协议是指所有事务必须分为两个阶段对数据项加锁和解锁。
- 获得封锁:对任何数据进行读、写操作之前,首先要申请并获得该数据的锁。
- 释放封锁:对在释放一个封锁之后,事务不能再申请和获得任何其他封锁。
事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件。