数据库系统概论笔记(11)
第11章 并发控制
并发概念:允许多个用户同时使用同一个数据库的数据库系统称为多用户数据库系统
事务执行方式:
- 串行执行:每个时刻只有一个事务运行
缺点:不能充分利用系统资源 - 交叉并发执行:事务并行操作,轮流交叉运行
特点:并没有真正地并行,但减少了处理机的空闲时间 - 同时并发执行:多个事务真正的并行运行
并发带来的问题:可能存取不正确的数据,破坏一致性
11.1并发控制概述
基本单位:事务是并发控制的基本单位
责任:保证事务的隔离性和一致性,对并发操作进行正确调度
并发操作带来的3种不一致:丢失修改、不可重复读、读“脏”数据
- 丢失修改:两个事务读入同一数据,T2提交的结果破坏了T1提交的结果,导致T1的修改被丢失
- 不可重复读:3种情况
1)T1读,T2改,T1再读得到与之前不同的值
2)T1读,T2删,T1再读却找不到
3)T1读,T2插,T1再读发现多了记录 - 读“脏”数据:T1改,T2读,T1撤销(数据恢复),T2再读发现不一致
产生不一致的原因:破坏了事务的隔离性(并发控制要正确调度并发操作保证隔离性)
并发控制的主要技术:封锁、时间戳、多版本并发控制等
11.2 封锁
概念:事务T对某个数据对象操作前,先向系统发出请求,对其加锁
两种基本的封锁类型:排他锁(X锁)、共享锁(S锁)
- 排他锁:又称写锁,对数据对象A加X锁,其它事务不能再对A加任何锁,其它事务也不能R、W它(但没共享锁概念时,其它事务可以通过select读它)
- 共享锁:又称读锁,对数据对象A加S锁,其它事务只能再对A加S锁,任何事务都不能W但可R它(任何事务要R都必须加共享锁,否则select读也不行)
注意:不同级别的协议,对select的限制不同,排他锁对“读”的解释也不同。
一级协议无共享锁概念,可用select读对象,即一级协议中加排他锁的对象可读
二级以上协议有共享锁概念,所有读操作都必须加共享锁,而排他锁不能容纳共享锁,即二级以上协议中加排他锁的对象不可读
11.3 封锁协议
封锁协议概念:何时申请X锁或S锁、持续时间、何时释放等规则
不同级别的封锁协议:
- 一级封锁协议:事务T在修改数据A之前必须先对X加锁,直到事务结束才释放(结束包括正常/非正常结束)
防丢失修改,并保证事务T是可恢复的
注:“修改数据A前加锁”意思是在首次读A前就要加,若事务T只有读A操作则一直不加锁 - 二级封锁协议:在一级封锁协议基础上,增加事务T在读取数据A之前加S锁,读完后(对有关该数据对象的连续操作完毕)可释放S锁
防丢失修改、读“脏”数据
注:“读完后可释放锁”意思是读完后立刻释放锁,下次要读时再加 - 三级封锁协议:在一级封锁协议基础上,增加事务T在读取数据A之前加S锁,直到事务结束才释放
防丢失数据、不可重复读、读“脏”数据
11.4 活锁和死锁
活锁
概念:某事务T可能永远等待(像OS中的饥饿效应,其它对R的请求封锁插了T对R的请求封锁的队)
避免活锁:采用先来先服务的策略
死锁
概念:事务T1等待T2,而T2又在等待T1,两个事务永远不能结束,形成死锁
死锁的预防:
- 一次封锁法:每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行
问题:降低了系统的并发度;很难事先确定每个事务要封锁的数据对象 - 顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实施封锁
问题:维护这样的资源封锁很困难;很难按规定的顺序去施加封锁
死锁的诊断与解除:普遍使用的解决死锁的办法
- 超时法:若一个事务的等待时间超过规定的期限,就认为发生了死锁
问题:规定的时间短,可能误判死锁;规定的时间长,死锁后不能及时发现 - 等待图法:
事务等待图:动态反映了所有事务的等待情况
检测死锁:发现等待图中存在回路
解除死锁:选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其它事务得以继续运行下去
11.5并发调度的可串行性
可串行化调度
可串行化调度:多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务时的结果相同
可串行性:当且仅当某个事务是可串行化的(可串行性是并发事务正确调度的准则)
冲突可串行化调度
冲突操作:不同事务对同一数据的读写操作和写写操作、同一事务的两个操作
不冲突操作:除了冲突操作以外的操作
不可交换:冲突的操作不可交换次序
冲突可串行化调度:一个调度Sc在保证冲突操作次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个调度Sc',若Sc'是串行的,称调度Sc为冲突可串行化的调度
(冲突可串行化调度是可串行化调度的充分不必要条件)
例:
Sc1=r1(A)w1(A)r2(A) w2(A)r1(B)w1(B) r2(B)w2(B)
交换w2(A)与r1(B)w1(B),得
Sc2=r1(A)w1(A) r2(A)r1(B)w1(B) w2(A)r2(B)w2(B)
交换r2(A)和r1(B)w1(B),得
Sc3=r1(A)w1(A)r1(B)w1(B) r2(A)w2(A)r2(B)w2(B)
Sc3是可串行化调度,所以Sc1是冲突可串行化调度
11.6 两段锁协议
目前普遍采用两段锁协议(2PL)实现并发调度的可串行性
两段锁协议:
- 概念:所有事务必须分两个阶段对数据项加锁和解锁
- 第一阶段:获得封锁,也称为扩展阶段
事务可以申请获得任何数据项上的任何类型的锁,但不能释放任何锁 - 第二阶段:释放封锁,也称为收缩阶段
事务可以释放任何数据项上的任何类型的锁,但不能再申请任何锁 - 充分不必要:事务遵守两段锁协议是可串行化调度的充分不必要条件
两段锁协议和一次封锁法:一次封锁法遵守两段锁协议,但两段锁协议不一定遵守一次封锁法(因此两段锁协议可能发生死锁)
11.7 封锁的粒度
封锁粒度:封锁对象的大小
封锁对象:逻辑单元(属性值、元组等)或物理单元(页、物理记录等)
封锁粒度与并发度和系统开销:
- 封锁粒度越大,能封锁的数据单元越少,并发度越小,系统开销越小
- 封锁粒度越小,能封锁的数据单元越多,并发度越大,系统开销越大
多粒度封锁
多粒度封锁:在一个系统中同时支持多种封锁粒度供不同的事务选择
多粒度树:根的节点是整个数据库,表示最大的数据粒度,叶节点表示最小的数据粒度
显式封锁:应事务要求直接加到数据对象上的锁
隐式封锁:某数据对象没有被独立加锁,但由于其上级结点加了锁使得该数据对象加上了锁
(检查封锁冲突不仅要检查显式封锁还要检查隐式封锁)
意向锁
意向锁:若一个结点加了意向锁,说明该结点的下层结点正在被加锁(对任一结点加锁时,必须对它的上层结点加意向锁)
三种意向锁:
- IS锁:即意向共享锁,某数据对象加了IS锁,表示其后裔结点拟(意向)加S锁
事务T1对R1某元组加S锁,先对关系R1和数据库加IS锁 - IX锁:即意向排他锁,某数据对象加了IX锁,表示其后裔结点拟(意向)加X锁
事务T1对R1某元组加X锁,先对关系R1和数据库加IX锁 - SIX锁:即共享意向排他锁,某数据对象加了SIX锁,表示对它加S锁,再加IX锁
事务T1对某表加SIX锁,表明T1要读整个表(S锁),同时更新个别元组(IX锁)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了