第十二章 并发控制
1.锁:
·共享的:如果事务Ti获得了数据项Q上的共享锁,则Ti可读但不可写Q。
·排他的:如果事务Ti获得了数据项Q上的排他型锁,则Ti既可读又可写Q。
如果Q上存在B类型锁,如果事务Ti可以立即获得数据项Q项上的锁,则我们就说A类型的锁和B类型的锁是相容的。
一个事务通过执行lock-S(Q)来申请数据项Q上的共享锁,lock-X申请数据项Q上的排他锁,通过unlock(Q)执行释放数据项Q上的锁。
哪种事务都不能正常执行的状态称为死锁。事务Ti可能永远不能取得进展,这称为饿死。
当事务Ti申请对数据项Q加M型锁时,并发控制管理器授权加锁的条件是:
(1)不存在在数据项Q上持有与M型锁冲突的锁的其他事务
(2)不存在在等待对数据项Q加锁且先于Ti申请加锁的事务
2 封锁协议:
-1. 两阶段封锁协议:
(1)增长阶段:事务可以获得锁但不可以释放锁
(2)缩减阶段:事务可以释放锁,但不能获得新锁。
*对于任何事务,在调度中该事务获得其最后加锁的位置被称为事务的封锁点。
-2.严格两阶段封锁协议:
(1)增长阶段
(2)缩减阶段
(3)事务持有的所有排它锁必须在事务提交后方可释放
-3. 强两阶段封锁协议:
(1)增长阶段
(2)缩减阶段
(3)事务提交之前不得释放任何锁
*锁转换 共享→排他(升级) 排他→共享(降级)
4.基于图的协议
*在树形协议中,可用的加锁指令只有lock-X。每个事务对一数据项最多能加一次所并且要遵循以下规则:
(1)Ti的首次加锁可以对任何数据项进行
(2)此后,Ti对数据项Q加锁的前提是Ti当前持有Q的父项上的锁
(3)对数据项解锁可以随时进行
(4)数据项被Ti加锁并解锁后,Ti不能再对该数据项加锁。
当事务Ti执行了未提交数据项的读操作,我们就在最后对该数据项执行了写操作的事务上记录一个Ti的提交集。
- 封锁
(1)实现
锁管理器可以实现为一个过程,他从事务接收消息并反馈消息。(使用锁表管理来实现管理)
eg.
(2)处理请求:
6.死锁处理:
(1)死锁预防
#1 通过对加锁请求进行排序或者要求同时获得所有的锁来保证不会发生循环等待
#2 每当等待有可能导致死锁时,进行事务回滚而不是等待加锁
机制:
#1:
最简单的机制要求每个事务在开始之前封锁它的所有数据项,要么全封锁要么不封锁;另一种机制:对所有的数据项强加一个次序,只能按照次序规定顺序封锁数据项;使用数据项与两阶段封锁关联的全叙,一单一个事务锁住了某个特定的数据项,他就不能申请顺序中位于该数据项前面的数据项的锁。
#2.抢占与事务回滚
#3 锁超时
申请锁的事务至多等待给定时间,若在此期间未授予改事务的锁,事务将超时回滚。
(2)死锁检测与死锁恢复
-1.死锁表述(等待图)
-2.死锁恢复:
7.多粒度:
意向锁类型意味着在树的较低层进行更小粒度显示加锁。
多粒度封锁协议:
8.基于时间戳的协议:
△ W-timestamp(Q):表示成功执行write(Q)的所有事务的最大时间戳
△ R-timestamp(Q):表示成功执行Read(Q)的所有事务的最大时间戳
Thomas写规则:
9.基于有效性检查的协议
这里面需要引入三个时间戳:
有效性测试:要求任何满足TS(k)<TS(j)的事务满足下面两个条件之一:
(1)Finish(k)<Start(j)
(2)所写的数据项集与j所读的数据项集不相交,并且k阶段的写阶段在j开始其有效性检查之前即 Start(j)<Finish(k)<Validation(j)
10.多版本机制
(1)多版本时间戳排序:
(3)多版本两阶段封锁
更新事务执行强两阶段封锁协议,即他们持有全部锁直到事务结束。
只读事务采用多版本时间戳排序协议。
11.快照隔离
每个事务开始执行时给它数据库一份“快照”,然后事务在该快照上操作和其他事务完全隔离开。
(1)更新事务的有效性检查步骤:
(2)串行化问题:
写偏斜可以理解为事务commit之前写前提被破坏,导致写入了违反业务一致性的数据,网上有个很好的简称为写前提困境,也就是读出某些数据,作为另一些写入的前提条件,但是在提交前,读入的数据就已被别的事务修改并提交,这个事务并不知道,然后commit了自己的另一些写入,写前提在commit前就被修改,导致写入结果违反业务一致性。
12.插入操作、删除操作与谓词读
幻读:查询期间 其他事务插入导致查询记录不同。
13.索引封锁技术
插入操作必须在关系的所有索引中加入新元组。将幻读实例转换为对索引叶节点上封锁的冲突。
14.
SQL隔离事务级别:
可串行化:保证可串行化调度
可重复读:保证事务两次读取结果相同。
已提交读:允许提交已经提交的数据,不保证可重复读。
未提交数据:允许读取未提交的数据。