并发控制与基本技术
一、并发控制
1. 概述
事务是并发控制的基本单位,并发控制机制的任务是:
① 对并发操作进行正确调度。
② 保证事务的隔离性。
③ 保证数据库的一致性。
2. 并发访问可能出现的问题
① 丢失修改
:指两个事务同时读取同一个数据,然后一个事务修改了这个数据并提交,另一个事务也修改了这个数据并提交,导致第一个事务的修改被覆盖,即数据被丢失。
② 不可重复读
:指一个事务在读取同一个数据两次时,第二次读取的数据与第一次不同,因为在两次读取之间,另一个事务修改了这个数据。
③ 读“脏”数据
:指一个事务读取了另一个事务未提交的数据,如果这个事务回滚或者修改了这个数据,则原来读取的数据就是“脏”的。
二、并发控制的主要技术
1、基本技术
① *(Locking)
② 时间戳(Timestamp)
③ 乐观锁(Optimistic Scheduler)
④ 多版本并发控制(MVCC)
2、*及锁的类型
2.1、什么是*
*就是事务T对某个数据对象(例如表、记录等)操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新次数据对象
。
*是实现并发控制的一个非常重要的技术。
2.2、基本*类型
2.2.1、排它锁(Exclusive Locks,简记为 X 锁
)
又称为写锁
,若事务T对数据对象A加锁X锁,则只允许T读取和修改A,其他任何事务都不能对A加任何类型的锁,直到T释放A上的锁,保证其他事务在T释放A上的锁之前不能再读取和修改A。
2.2.2、共享锁(Share Locks,简记为 S 锁
)
又称为读锁
,若事务T对数据对象A加锁S锁,则T可以读A但不能修改A,其他任何事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。保证其他事务可以读A,但在T释放A上的S锁之前不能对A做任何的修改操作。
3、活锁和死锁的概念
活锁:因为进程不停地改变自己的状态而无法终止。
死锁:因为互相等待对方占用的资源,导致两个或多个进程都无法继续执行。
4、并发调度的可串行性
什么样的调度是正确的调度?可串行化的调度是正确的调度
。
可串行化的调度的定义:多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行它们时的结果相同
,称这种调度策略为可串行化的调度。
可串行性:是并发事务正确调度的准则,按照这个准则一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度
。
冲突可串行化调度
冲突操作:指不同事务对同一数据的读写操作和写写操作。
Ri(X)与 Wj(X) /* 事务Ti 读 X ,Tj 写 X ,其中 i ≠ j /
Wi(X)与 Wj(X) / 事务Ti 写 X ,Tj 写 X ,其中 i ≠ j */
这两种情况是冲突的,不能更换位置。
注:可串行性调度无法推出是冲突可串行化调度。
5、两段锁
数据库管理系统普遍采用两段锁协议的方法实现并发调度的可串行性,从而保证调度的正确性。
注:可串行性调度无法推出是采用两段锁。
5.1、两段锁协议定义
指所有事务必须分两个阶段对数据项加锁和解锁,即在对任何数据进行读、写操作之前,事务首先要获得对该数据的*;在释放一个*之后,事务不再申请和获取任何其他*。
5.2、两段锁的含义
事务分为两个阶段
- 获得锁,也称为扩展阶段。事务可以申请获得任何数据项上的任何类型的锁,但是不能释放任何锁。
- 释放*,也称为收缩阶段。事务可以释放任何数据项上的任何类型的锁,但是不能再申请任何锁。
5.3、两段锁协议与防止死锁的一次*法的异同
① 一次*法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行,因此一次*法遵守两段锁协议。
② 两段锁协议并不要求事务必须一次将所有要使用的数据全部加锁,因此遵守两段锁协议的事务可能发生死锁。
6、*的粒度
*对象的大小称为*粒度。
*的对象:
- 逻辑单元:属性值、属性值的集合、元组、关系、索引项、整个索引、整个数据库等。
- 物理单元:页(数据页或索引页)、物理记录等。
【说明】
① *粒度与系统的并发度和并发控制的开销密切相关。
② *的粒度越大,数据库能*的数据单元就越少,并发度就越小,系统开销也就越小。
③ *的粒度越小,并发越高,但系统开销也就越高。
多粒度*
-
多粒度*是指在一个系统中同时支持多种*粒度供不同的事物选择。
-
选择*粒度的原则----考虑*开销和并发度两个因素,具体为:
a. 处理多个关系的大量元组的用户事务:数据库为*单位。
b. 处理大量元组的用户事务:以关系为*单位。
c. 只处理少量元组的用户事务:以元组为*单位。 -
多粒度树:以树形结构来表示多级*粒度,根节点是整个数据库,表示最大的数据粒度,叶节点表示最小的数据*粒度。
-
多粒度*协议:允许每个结点被独立加锁,对一个结点加锁意味着这个结点的所有后裔结点也被加以同样类型的锁。分为两种形式*:显式*和隐式*。
a. 显式*:直接加到数据对象上的*。
b. 隐式*:是该数据对象没有独立加锁,是由于其上级结点加锁而使该数据对象加上了锁。
7、意向锁
引进目的:提高对某个数据对象加锁时系统的检查效率。
意向锁的含义
:如果对一个结点加意向锁,则说明该结点的下层结点正在被加锁。对任一结点加基本锁,必须先对它的上层结点加意向锁。
常用意向锁:
- 意向共享锁(简称
IS锁
):如果一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁。
【例】事务 T1 要对 R1 中某个元组加锁 S 锁,则首先对关系 R1 和数据库加 IS 锁。 - 意向排它锁(简称
IX锁
)
【例】事务 T1 要对 R1 中某个元组加锁 X 锁,则首先对关系 R1 和数据库加 IX 锁。 - 共享意向排他锁(简称
SIX锁
)
【例】对某个表加 SIX 锁,则表示该事务要读整个表(所以要对该表加 S 锁),同时会更新个别元组(所以要对该表加 IX 锁)
8、锁的强度
指它对其他锁的排斥程度,一个事务在申请*时以强锁代替弱锁是安全的,反之则不然。