数据库系统的并发控制
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
我们能够进一步改善两段锁协议,可 以设计一个机制实现共享锁和互斥锁之间 的转换。当一个事务将共享锁转换为互斥 锁时,这个事务可能需要等待其他事务释 放在该数据上的锁。
T1
LOCK_X(B) READ(B) B:=B-50 WRITE(B)
T2 造成了死锁
LOCK_S(A); READ(A) LOCK_S(B) READ(B) DISPLAY(A+B) UNLOCK(A) UNLOCK(B)
时间印协议
时间印协议是另一种保证事务串行性的协议, 它与基于锁的协议不同的地方是:事先选择事务的 串行顺序。
时间印的概念:为系统中的每个事务Ti,我们为其分配一个唯 一的确定值,称为时间印,记做TS(Ti)。 Ti的时间印是在 它运行之前分配的。如果事务Tj在事务Ti的时间印被分配后进 入系统,则TS(Ti)<TS(Tj),时间印协议必须保证所产生的调 度等价于一个串行调度,在这个串行调度中Ti先于Tj。 有两种简单的方法来实现这一机制: 1、使用系统时钟值作为时间印
(2)、设事务T要求执行WRITE(Q)
a、如果TS(T)<R_TS(Q),则T要写的Q值已经被一个较大 时间印的事务读过,所以拒绝执行这个WRITE(Q)操作,并 放弃T b、如果TS(T)<W_TS(Q),则T要写一个已经过时的Q值,所 以拒绝执行这个WRITE(Q)操作,并放弃T。
c、如果TS(T)不满足(1)和(2)的条件,则执行这个 WRITE(Q)操作,令W_TS(Q)=MAX{W_TS(Q),TS(T)}。 由上述时间印协议放弃的事务T将重新分配一个新的 时间印,并重新启动执行。
该事务上拥有一个互斥锁,锁管理器能采用两种策略之一:
Wait-die :如果Ti的优先级更高,它可以等待,否则将被放 弃
Wound-wait:如果Ti的优先级更高,则放弃Tj, 否则Ti等 待。
上面两种策略,都可以防止死锁。
我们应该保证没有一个事务将永远不被执行。 采取的策略是当一个事务被放弃时并且重新开始时, 它应该被给予与上一次同样的时间戳。
T2 READ(A) READ(B) DISPLAY(A+B)
READ(A)
A:=A+50 WRITE(A) commit
commit
T1 完成两个帐户 之间的转帐,而 T2显示两个帐户 的余额之和 如果串行执行T2 显示的值为300
T1
LOCK_X(B) READ(B) B:=B-50 WRITE(B)
两段锁协议的两种变体:
• •
Strict two-phase locking protocol (STPL) Rigorous two-phase locking protocol (RTPL)
STPL 在两段锁协议的基础上, 又加入了如下附加条件:
被一个事务所持有的排它锁必须在该事务提交时才能释放。
如果一个事务要对某个节点加锁,那么必须搜索从根到 该节点路径上的所有节点,如果在这些节点中的一个或多 个上加有互斥锁,则该事务必须等待。这种方法的效率很 低,更为有效的方法是引进一个新锁,称为意向锁。任何 一个节点被加锁时,它的先辈节点都被先被加以意向锁。 意向锁分为三种: 一种是共享意向锁, 简记为IS 另一种是互斥意向锁,简记为IX 一种是共享意向互斥锁, 简记为SIX。
多粒度封锁
多粒度封锁是指在一个系统中同时支持多种封锁粒度。
多粒度锁定协议支持多种并发控制粒度的并发控制协议。 多重粒度树 : 多种粒度数表示多种粒度的嵌套。 DB
A1
Fa a b c Fb d e
A2
Fc f
多粒度协议允许多重粒度树中的每个节点被独立地加锁。 这里我们使用共享和互斥两种类型的锁。一个节点被加锁 意味着这个节点的所有后裔节点也被加以同样类型的锁。
DATA
持有
T2(10)
T1(5) T3(15) Wait-idle : T1:WAIT T3: ROLLBACK Wound-wait:
T1: T2 ROLLBACK
T3: WAIT
死锁的检测与处理
死锁是比较少见的,并且即使存在,也涉及到较少的 事务。因此,与其采取 措施来预防死锁,还不如对死 锁进行检测,如果出现及时对其处理。 为了检测死锁, 锁管理器要维护一个等待图, 在等 待图中的一个节点是对应着一个活动事务,当Ti等待 Tj来释放一个锁时,那么在图中出现了一个从Ti到Tj 的边。
例:
假定事务T1读Fa的a记录, T1锁定路径为: IS a S
database
IS
A1
Fa
IS 假定事务T2更新Fa的记录b database A1 Fa b
IX IX IX X 假定事务T3读Fa的所有记录。
database A1 Fa
IS
IS
S
假设T4要读整个数据库:
database
S 上述四个事务中,T1、T3、T4 可以并发执行。事务T2 可以同事务T1并发执行,但不能同事务T3、T4并发执行。
这一需求保证了任何尚未提交的数据不可能被其它事务所 读取。 RTPL在两段锁协议的基础上, 加入了如下附加条件: 一个事务所持有的所有锁只有当提交时才能被释放, 可以 证明如果使用RTPL, 多个事务可以依照提交顺序串行化。
T1
LOCK_S(A) READ(A) LOCK_X(B) UNLOCK(A)
RPTL
LOCK_X(A); READ(A) A:=A+50 WRITE(A) UNLOCK(A) COMMIT
T1 READ(a1) READ(a2) ••• ••• ••• READ(an)
T2 READ(a1) READ(a2) DISPLAY(a1+a2) Commit
WRITE(a1)
commit T1在对a1进行写操作,并且这个操作是事务的最 后一个操作,如果为a1开始时就加一个互斥锁, 那么只有当T1事务结束之后才能进行事务T2的操 作,降低了并行性。
一个保证可串行性的方法是在互斥的方式下存取数据, 即当一个事务存取数据时不允许其他事务修改这个数据项。
(一)、锁的概念 锁可以分为两种类型: (1) 共享锁
如果事务T得到了数据项Q上的共享锁,则T可以读这个 数据项,但不能写这个数据项。共享锁表示为S。
(2) 互斥锁
如果事务T得到了数据项Q上的互斥锁,则T即可以读这个 数据项,也可以写这个数据项
T2
UNLOCK(B)
LOCK_S(A) READ(A) UNLOCK(A) LOCK_S(B) READ(B) UNLOCK(B) DISPLAY(A+B) commit LOCK_X(A) READ(A) A:=A+50
S事务T2 显示的值为 250
WRITE(A)
UNLOCK(A) commit
s
x
true
false
false
false
二、封锁协议
在运用X锁和S锁对数据对象进行加锁时,还需 要约定一些规则, 例如: 何时申请X锁或S锁、 持锁时间、何时释放等,这些规则称为封锁协议。 对封锁方式规定不同的规则, 就形成了各种不同 的封锁协议。
T1 READ(B) B:=B-50 WRITE(B)
T1
S(A) R(A)
T2
T3
T4
T1
X(B) W(B)
T2
T4
S(C)
R(C)
S(B)
T3
X( C)
X(B)
X(A)
封锁的粒度
封锁对象的大小称为封锁粒度。
以关系数据库为例, 封锁对象可以是这样一些逻辑单元: 属性值、属性值的集合、元组、关系、索引项、整个索引直 至整个数据库。 封锁粒度与系统的并发度和并发控制的开销密切相关。 封锁的粒度越大, 并发度越小,系统开销也小。反之, 封锁的粒度越小, 并发度高, 但系统的开销也大。 选择封锁粒度时,应同时考虑系统开销和并发度两个因素, 以求达到最大的效果。
如果一个节点被加以IS锁,则该节点的后裔节点正在被加共 享锁;如果一个节点被加以IX锁,则该节点的后裔节点正在 被加互斥锁。如果一个节点被加以SIX锁,则以该节点为根的 子树已经被加以共享锁,而该节点的后裔正在被加以互斥锁。
IS
IS true IX true X true
IX
S
SIX X
true true true false true false false false false true false false
三、 两阶段锁协议
两段锁协议要求每个事务分为两个阶段进行数据锁的加锁 和解锁。 阶段1 加锁阶段 在这个阶段,事务可以申请获得任何 数据项上的任何类型的锁,但是不能释放任何锁 阶段2 解锁阶段 在这个阶段,事务可以释放任何数据 项上的任何类型的锁,但是不能申请任何锁。
每个事务开始后即进入加锁阶段,申请获得所有的锁,当 事务第一次释放锁时,该事务进入解锁阶段。进入解锁阶 段的事务不能再申请任何锁。
2、使用逻辑计数器的值作为时间印
为了实现上述时间印协议,为每个数据项分配两个时间印值。
(1)、 W_TS(Q)=MAX{TS(Ti) Ti 成功执行了WRITE(Q)} (2)、 R_TS(Q)=MAX{TS(Ti) Ti成功执行了READ(Q)}
时间印协议定义如下:
(1)、 设事务T要执行READ(Q) a、如果TS(T)<W_TS(Q), 则T所要求的Q值已经被具有较大时 间印的事务重写,所以拒绝T的READ(Q)操作,并放弃T。 b、如果TS(T)>=W_TS(Q),则执行这个READ(Q)命令,并令 R_TS(Q)为MAX{R_TS(Q), TS(T)}
T2
SPTL LOCK_X(A);
READ(A)
A:=A+50 WRITE(A) UNLOCK(A) COMMIT
READ(B) B:=B-50 WRITE(B) DISPLAY(A+B) UNLOCK(B) COMMIT
T1
LOCK_S(A) READ(A)
T2
LOCK_X(B)
READ(B) B:=B-50 WRITE(B) DISPLAY(A+B) UNLOCK(B) UNLOCK(A) COMMIT
每个事务在存取一个数据项之前必须获得这个数据项上的锁。 一个事务需要获得的锁的类型取决于它将在数据项上执行什 么样的操作。给定各种锁的类型,我们可以如下定义这个锁集 合上的相容关系。 令A和B表示任意类型的锁,设事务Ti在数据项Q上要求一 个A型锁,事务Tj已经在Q上有一个B型锁,如果事务Ti能够获 得Q上的A型锁,则说A型锁和B型锁是相容的。 下图表示锁相容矩阵 s x 共享锁可以被多个同时拥有, 但对于互斥锁,只有当一个 数据项上的所有锁都被释放 时,一个事务才能获得在该 事务上的互斥锁。
处于永久等待
LOCK_X(A) READ(A) A:=A+50 WRITE(A) UNLOCK(A) UNLOCK(B)
死锁的预防
我们可以通过给每个事务一个优先级来预防死锁,确保一 个优先级较低的事务等待优先级较高的事务。赋予优先级的 一个方法是当事务启动时给每个事务一个时间戳,时间戳越 低,优先级越高,即越老的事务优先级越高。 如果一个事务Ti在某一数据上请求一个锁,并且事务Tj在
SIX true false false false false
Biblioteka Baidu
X false
false false false false
多重粒度锁协议
1、必须遵守上面的相容矩阵 2、多重粒度树的根首先被加锁,锁的类型不限 3、仅当Q的父节点已经被T加以IS 或IX锁时,Q才可以 被T加S或IS锁。 4、仅当Q的父节点已经被T加以IS或SIX型锁时,Q才可 以被T加X、SIX或IS型锁。 5、仅当T还没有释放过任何锁时,T才可以对节点加锁 6、仅当Q的后裔节点都不被T加锁时,T才可以解锁Q。 从多重粒度协议可以看出加锁时,采用的从上向下的顺序。而 解锁时,采用的是从下向上的顺序。
并发控制
在事务一章中,我们已经介绍了由于多个事务 并发执行可能引起三种异常: 读脏数据、不可 重复读、重写未提交的数据。 引起这些异常的 原因是并发操作破坏了事务的隔离性。 并发控 制的目的就是用正确的方式调度并发操作, 使 事务之间不会相互影响, 即保证并发运行事务 的可串行性。
一、基于锁的并发控制协议