文章目录
封锁
- 事务T对某个数据对象操作之前,向系统发出请求,对数据加锁。加锁之后,只有事务T对数据对象有控制,其它事务不能更新该数据对象。
- 为了实现并发控制,保证数据库的一致性。
类型
不同的锁有不同的限制。
排他锁(exclusive lock)(写锁)(X锁)
事务T对数据对象A加X锁之后,T可以读写A,其它事务不能对A加其它锁。
共享锁(share lock)(读锁)(S锁)
事务T对数据对象A加X锁之后,T只可以读A。其它事务可以对T加S锁。
封锁协议
规定何时申请锁、何时释放锁以及持锁时间
以下A=10包括读取A,给A赋值,写入A三个过程
一级
事务在修改数据之前必须加X锁,事务结束时释放。
这样事务T在修改数据至事务结束,其它事务都不可修改数据,可防止丢失修改
假设A为4
防止丢失修改
时间序列 | 事务1 | 事务2 |
---|---|---|
1 | 对A请求X锁 | |
2 | 对A加X锁 | |
3 | 对A请求X锁 | |
4 | A=10 | 等待 |
5 | 释放X锁 | 等待 |
6 | 对A加X锁 | |
7 | A=6 | |
8 | 释放X锁 |
不可防止读脏数据
时间序列 | 事务1 | 事务2 |
---|---|---|
1 | 对A请求X锁 | |
2 | 对A加X锁 | |
3 | A=10 | |
4 | 读取A(10) | |
5 | 撤销操作A(4) | |
6 | 释放X锁 |
不可防止不可重复读
时间序列 | 事务1 | 事务2 |
---|---|---|
1 | 读取A(4) | |
1 | 对A请求X锁 | |
2 | 对A加X锁 | |
3 | A=10 | |
4 | 读取A(10) | |
5 | 释放X锁 |
二级
在一级协议的基础上,事务在读取数据之前加S锁,读完释放S锁。
这样事务T修改数据之后,不会有其它事务读取,即使T撤销操作,也不会造成读脏数据
防止读脏数据
时间序列 | 事务1 | 事务2 |
---|---|---|
1 | 对A请求X锁 | |
2 | 对A加X锁 | |
3 | 对A请求S锁 | |
4 | A=10 | 等待 |
5 | 撤销操作A(4) | 等待 |
6 | 释放X锁 | 等待 |
7 | 对A加S锁 | |
8 | 读取A(4) | |
9 | 释放S锁 |
不可防止不可重读
时间序列 | 事务1 | 事务2 |
---|---|---|
1 | 对A请求S锁 | |
2 | 对A加S锁 | |
3 | 读取A(4) | 对A请求X锁 |
4 | 释放S锁 | 等待 |
5 | 对A加X锁 | |
6 | 对A请求S锁 | A=10 |
7 | 等待 | 释放X锁 |
8 | 对A加S锁 | |
9 | 读取A(10) | |
10 | 释放S锁 |
三级
在二级协议的基础上,延长释放S锁的时间,事务结束时释放S锁。
这样在事务的两次读取之间,不会有其它事务修改数据,可防止不可重复读
时间序列 | 事务1 | 事务2 |
---|---|---|
1 | 对A请求S锁 | |
1 | 对A加S锁 | |
2 | 读取A(10) | 对A请求S锁 |
3 | 对A加S锁 | |
4 | 读取A(10) | |
5 | 释放S锁 | |
6 | 读取A(10) | |
7 | 释放S锁 |
活锁
事务1封锁某数据后,事务2请求封锁并等待,事务1释放锁之后,事务3请求封锁并封锁某数据,事务3释放锁之后,事务4请求封锁并封锁某数据……事务2一直等待。
解决办法
- 按请求封锁的先后顺序,对事务排队
- 数据锁释放时,首先批准队列中的第一个事务获得锁(封锁数据)
死锁
事务T1和T2各自封锁了数据R1和R2后,又各自请求封锁数据R2,R1。事务T1与T2则一直等待对方释放数据。
解决办法
- 预防死锁
- 一次封锁法
- 顺序封锁法
- 死锁的诊断
- 超时法:一个事务等待的时间超过规定时间则判断为发生了死锁
- 等待图法:用节点表示事务,用有向边表示事务间的等待关系,如果有回路,则发生了死锁
- 死锁的处理
- 选择死锁中代价最小的事务,撤销之,释放其所有锁
两段锁协议(2PL)
内容:所有事务分两个阶段对数据项加锁和解锁。
- 对任何数据进行读写操作之前,必须对数据加锁。
- 释放一个封锁之后,不再对数据加锁。
两段锁协议与三级封锁协议目的不同,前者保证并发调度的正确性,后者保证数据库的一致性。
封锁粒度
封锁对象的大小称为封锁粒度
三级粒度树
多粒度封锁协议
- 允许多粒度树的每个节点被加锁
- 对一个节点加锁,意味着对该节点的所有子节点加同种类型的锁
- 一个数据对象可以既有显示封锁,又有隐式封锁
- 显示封锁:直接加到数据对象的锁
- 隐示封锁:由于其父节点被加锁而引起其加锁
意向锁
- 对一个节点加锁,必须对其上层节点加意向锁
- 对一个节点加意向锁,表示该节点的下层节点被加了锁
意向共享锁(Intent Share Lock)(IS)
意向排它锁(Intent Exclusive Lock)(IX)
共享意向排它锁(Share Intent Exclusive Lock)(SIX)
举例:
对于学生表,修改张三的姓名,则对张三的姓名加X锁,对张三这一元组加IX锁,对学生表加SIX锁。
如果是读取张三的姓名,则对张三的姓名请求S锁,对张三这一元组请求IS锁,对学生表加IS锁。
锁的相容矩阵
T1,T2代表事务,–代表不加锁,Y代表可以获得锁,N代表不可以获得锁,并需要等待。