并发
事务:一次读写操作序列
调度:一个或者多个事务的重要操作按时间顺序执行的一个序列。
串行调度:不同事务在执行过程中没有交叉的调度。
导致数据库状态不一致的可能原因:故障发生、并发事务数据的共享
并发操作可能引起数据的不一致:丢失修改、不可重复读、读取到脏数据
Why:事务的隔离性被破坏,事务间相互干扰
并发控制的目的
控制并发事务的执行步骤保证事务都可以正确的执行,从而保证数据库的一致性。
操作部件:事务管理器的调度器
可串行化调度及其判定方法
可串行性: 多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行它们时的结果相同。
并发事务操作的正确与否: 是否具有可串行性
并发控制思想: 延迟一些操作,甚至终止一些操作。
关于冲突
冲突的操作 : 涉及同一数据元素,且至少有一个写操作。
如果一个调度冲突等价于一个串行调度,我们说该调度是 冲突可串行化
的。
冲突可串行化
调度是可串行调度的 充分条件。
优先图P(S):
结点:表示调度S中的事务
弧:当下列条件成立时, 可画弧
T
i
→
T
j
Ti \rightarrow Tj
Ti→Tj
-
p
i
(
A
)
,
q
j
(
A
)
p_i (A) , q_j (A)
pi(A),qj(A) 是S 中的操作 (即:来自不同事务的两个
操作涉及同一元素
) - p i ( A ) < s q j ( A ) p_i (A) < _s q_j (A) pi(A)<sqj(A) (即: p i (A) 发生在q j (A) 之前 )
-
p
i
p_i
pi 和
q
j
q_j
qj 中
至少一个是写操作
判断调度S是否冲突可串行化:
构造S的优先图,并判断其中
是否有环
。如果有,则S不是冲突可串行化的,否则,S 是冲突可串行化的。
有向无环图的拓扑排序问题
并发控制的主要技术
- 封锁技术
- 时间戳
- 有效性检查
封锁技术
lock、unlock
- 事务在读写操作之前需要对元素进行加锁lock,时候解锁unlock。
- 任何两个事务不能同时封锁同一元素。
- 两阶段锁(2PL) ,在对数据读写之前首先申请并获得封锁(上升阶段),释放一个封锁后不再申请和获得任何其他封锁(收缩阶段)
2PL:读写之前加锁,解锁时候不获取任何锁
死锁预防
- 一次封锁法
- 顺序封锁法
死锁诊断与解决
- 诊断 :超时法,等待图法
- 解决 : 选择一个处理死锁代价最小的事务,强行撤销。
共享锁
读操作并不会产生冲突!!!
提出两种类型的锁:
- 共享锁(读锁,S 锁)
- 排它锁 (写锁,X 锁)
三个规则:(满足则调度是可串行的)
- 事务的一致性,读前加 S锁,写前加 X 锁,处理结束要解锁
- 对A加S锁后,未释放前不可加X锁;对A加X锁后,未解锁前不可加S或者X锁.
- 2PL:锁升级;
a. 如果锁升级采用申请多个锁的方式(如 S → S , X S \rightarrow {S, X} S→S,X) ,则没有变化。
b. 如果锁升级时采用先释放再申请的方式(如 S → X S \rightarrow X S→X) ,则在上升阶段允许。
封锁协议及事务隔离程度
封锁协议
一级封锁协议
修改数据之前加X锁,直至事务结束
solve:丢失修改
二级封锁协议
写数据之前加X锁,直至事务结束
读取数据之前加S锁,读完释放
solve:丢失修改、读脏数据
三级封锁协议
写数据之前加X锁,直至事务结束
读数据之前加S锁,直至事务结束
solve:丢失修改、读脏数据、不可重复读
隔离程度
- 可串行化
- 可重复读:一个事务两次读取数据项期间,其他事务不得更新数据
- 已提交读:只允许读取已提交数据,但不要求可重复读
- 未提交读:只能读取未提交数据
均不允许“脏写”,数据在被一个事务写的时候,在未提交或中止之前不允许其他事务进行写操作。