在这个“圣诞节”,或许你没有平安果,没有NPY,但你有《数据库原理与应用》可以复习啊!
上次谈了事务特性以及保证持久性的数据库恢复技术,这次谈保证隔离性的并发控制。

重点一览
破坏隔离性带来的数据不一致
三级封锁协议及效果
死锁的检测及解决
可串行化调度的判断与两段锁协议
多粒度封锁协议,意向锁及加锁顺序
锁的相容矩阵及巧记
并发控制及其必要性

破坏隔离性带来的数据不一致
丢失修改:T1修改数据后,数据又被T2修改成其他值。
读脏数据:T1读取T2修改后的数据后,T2触发回滚,数据恢复未修改前的状态。
不可重复读:T1读取数据后
T2修改此数据,T1再次读取数据,但和第一次读取的数据已不一致。
T2增加或删除数据,T1再次读取数据,读取数据不一致(幻影现象)
并发控制
用正确的方式调度并发操作,使一个事务的执行不受其他事务的干扰,避免造成数据的不一致。
封锁和封锁协议

锁
事务在对数据对象进行操作之前,先向操作系统申请对该对象加锁。加锁后其他事务在操作该对象时会受到限制。
根据受到的限制不同,最基础的锁分为两类:共享锁和排他锁。
共享锁(读锁,S):已加S锁的对象只能再加S锁。
排它锁(写锁,X):已加X锁的对象不能再加任何锁。
封锁协议
有了锁,我们就要考虑:
加什么锁
何时加锁,何时释放
规定这些内容的规则被称为封锁协议。常用的封锁协议是三级封锁协议。
三级封锁协议
一级封锁协议:事务在修改数据之前必须先对其加X锁,直到事务结束才释放。
二级封锁协议:一级封锁协议 + 事务在读取数据前必须先加S锁,读完后即可释放S锁
三级封锁协议:一级封锁协议 + 事务在读取数据之前必须先对其加S锁,直到事务结束才释放
三级封锁协议的异同及效果对比见下表:

活锁与死锁

封锁技术可以有效地解决并行操作的一致性问题,但也带来一些新的问题,导致事务长期等待无法运行。
概念
活锁:某个事务请求封锁,但一直被其他事务插队,解决方法是先到先服务
死锁:两个以上的事务分别请求封锁对方已经封锁的数据
死锁的预防
一次封锁法
一次封锁所有要使用的数据,否则不继续执行
缺点:降低并发度:难以事先确定要使用的数据
顺序封锁法
预先对数据对象规定封锁顺序,所有事务按顺序封锁
维护成本高,难于实现
死锁的诊断与解除
思路:允许发生死锁,由DBMS定期检测并解除
检测方法:
以运行中的事务为结点,等待关系为有向边,构建有向图(事务等待图)
并发控制子系统周期性检查回路,存在回路则认为发生死锁
若一个事务的等待时间超出预设时限,就认为发生死锁
实现简单
可能发生误判;合理预设时限难度较大
超时法:
等待图法
消除方法:回滚策略
事务开始时,赋予每个事务唯一的时标
当一个事务对其他事务封锁的数据请求时,新事务退回,等待重试
事务退回重试后,时标保持不变
并发调度的可串行化

可串行化的调度策略
多个事务的并发执行是正确的,当且仅当其结果与某一次序串行地执行它们时的结果相同。称这种调度为可串行化调度。
可串行性
一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度。
这是并发事务正确调度的准则。
可串行化调度判断
对一个并发调度,若在保证冲突操作次序不变的情况下,通过交换两个事务不冲突操作的次序,可获得一个串行调度。则称该并发调度为冲突可串行化调度。
两个事务不冲突的操作:
不同事务对同一数据的读读操作
不同事务对不同数据的任意操作
可串行化调度保障——两段锁协议
读写前加锁(扩张阶段)
释放锁后不能再申请锁(收缩阶段)
注意
可串行化调度的判断方法和两段锁协议内容都是充分而非必要条件,可能有 不符合以上规则但仍具有可串行性的调度。最终还是要看并发调度的结果是否与某一串行调度的结果相同。
两段锁不能预防死锁
多粒度封锁

封锁粒度
封锁粒度指封锁目标的大小。
封锁粒度大,则并行度低,效率低,但开销小;封锁粒度小,并行度和效率都高,但系统开销大。
多粒度封锁
DBMS同时支持多种封锁粒度,供不同事务选择。
不同封锁粒度以树的形式组织,称为多粒度树。根节点是整个数据库。
多粒度封锁协议允许多粒度树的每个节点被独立地加锁。对一个结点加锁,意味着其所有后裔结点加了同样的锁。
多粒度封锁的实现
封锁的两种方式
显式封锁:直接在本结点加锁
隐式封锁:本结点没有直接加锁,但在上层加了锁
冲突检查:
由于新出现隐式封锁,新加锁时需要考虑:
这么多检查,尤其是第三个,下层结点何其多,烦死了好伐!
所以出现了一种新型锁——意向锁,可以考虑检查冲突3。
是否与本结点已有显式封锁冲突
是否与本结点已有隐式封锁冲突
新加锁对下层结点的隐式封锁是否与其已有显式封锁冲突
意向锁——免于逐个检查下层结点的显式封锁
如果对一个结点加意向锁,说明正在对其下层结点加锁;要想对结点加锁,必须对其上层结点加意向锁。(充分必要)
意向锁分类:
SIX锁:S+IX锁,表示将对整个表进行读取,同时对部分子结点做修改。
IX锁:将对下层结点加X锁
IS锁:将对下层结点加S锁
处理顺序:在多粒度树上,从上而下申请,从下而上释放(与两段锁协议神似)。
锁的相容矩阵
内容

一种速记
相容矩阵对称,记一半即可(废话)
先找X锁,X锁和所有锁冲突
再找IS锁,和X锁之外的的锁都相容
再找SIX锁,和除X和IS之外的锁都冲突
IX,S锁自相容
S与IX锁冲突
(穷途末路,无奈之举,建议理解原理)
微信不开放留言功能,若对文章内容有疑问或发现错误想要指正请进入公众号留言。
点击“阅读原文”,访问我的个人博客“于小江的百宝箱”,浏览更多数据库笔记!




