3.8.4 封锁协议
本课核心知识点整理
封锁协议解决什么
事务并发会破坏隔离性,封锁协议通过“访问数据前先加锁”来控制读写冲突。课程字幕说明,封锁协议种类很多,软件设计师目前更常考基础的 S 锁和 X 锁原则;两段锁、三级封锁协议了解即可。
S 锁与 X 锁
| 锁 | 英文 | 中文 | 用途 | 特点 |
|---|---|---|---|---|
| S 锁 | Share Lock | 共享锁、读锁 | 读取数据 | 多个事务可同时读 |
| X 锁 | Exclusive Lock | 排他锁、写锁、独占锁 | 修改数据 | 独占数据项,阻止其他读写锁 |
S 锁用于保护读操作:别人也可以读,但不能写。X 锁用于保护写操作:别人既不能读,也不能写。
锁兼容矩阵
判断加锁是否成功时,直接看数据项当前已有锁和新申请锁是否兼容:
| 当前已有锁 | 申请 S 锁 | 申请 X 锁 |
|---|---|---|
| 无锁 | 成功 | 成功 |
| S 锁 | 成功 | 失败 |
| X 锁 | 失败 | 失败 |
这就是字幕里的核心原则:已经加了 S 锁,还可以继续加 S 锁,但不能加 X 锁;已经加了 X 锁,其他事务不能再加任何锁。
例题式判断
若事务 T1 已对 D1 加 S 锁:
| 其他事务申请 | 结果 | 原因 |
|---|---|---|
对 D1 加 S 锁 | 成功 | 共享读兼容 |
对 D1 加 X 锁 | 失败 | 写锁与已有读锁冲突 |
若事务 T1 已对 D2 加 X 锁:
| 其他事务申请 | 结果 | 原因 |
|---|---|---|
对 D2 加 S 锁 | 失败 | X 锁独占 |
对 D2 加 X 锁 | 失败 | X 锁互斥 |
做选择题时,先逐个数据项标记已有锁,再判断后续每个申请是否兼容。
三级封锁协议的理解
虽然字幕强调考试更常见 S/X 锁原则,但传统教材常把封锁协议分为三级:
| 协议 | 加锁要求 | 能防止 |
|---|---|---|
| 一级封锁协议 | 修改数据前加 X 锁,事务结束释放 | 丢失修改 |
| 二级封锁协议 | 一级基础上,读数据前加 S 锁,读完释放 | 丢失修改、读脏数据 |
| 三级封锁协议 | 一级基础上,读数据前加 S 锁,事务结束释放 | 丢失修改、读脏数据、不可重复读 |
级别越高,锁保持时间越长,隔离性越强,但并发度越低。三级协议防不可重复读,是因为第一次读后 S 锁不立刻释放,其他事务不能在本事务结束前修改该数据。
封锁的副作用
加锁能提高一致性,但也可能带来等待和死锁。死锁是多个事务互相等待对方释放锁。软考这一章通常不展开死锁处理,只需知道封锁并非没有代价:它通过降低一部分并发自由度换取正确性。
做题路线
- 写操作看 X 锁,读操作看 S 锁。
- 已有 S 锁时,其他 S 锁可成功,X 锁失败。
- 已有 X 锁时,其他任何 S/X 锁都失败。
- 问“防哪些并发问题”时,用一级/二级/三级协议表判断。
例题
事务修改数据前通常应加:
能防止丢失修改、读脏数据和不可重复读的封锁协议是:
自查要点
- 共享锁和排他锁的区别是什么?
- 一级、二级、三级封锁协议分别能防什么?
- 为什么三级封锁协议会降低并发度?