当前位置:Gxlcms > 数据库问题 > 数据库 - 并发控制

数据库 - 并发控制

时间:2021-07-01 10:21:17 帮助过:50人阅读

]飞机订票系统中的一个活动序列 ① 甲售票点(甲事务)读出某航班的机票余额A,设A=16; ② 乙售票点(乙事务)读出同一航班的机票余额A,也为16; ③ 甲售票点卖出一张机票,修改余额AA-1,所以A15,把A写回数据库; ④ 乙售票点也卖出一张机票,修改余额AA-1,所以A15,把A写回数据库 结果明明卖出两张机票,数据库中机票余额只减少1 这种情况称为数据库的不一致性,是由并发操作引起的。 在并发操作情况下,对甲、乙两个事务的操作序列的调度是随机的。 若按上面的调度序列执行,甲事务的修改就被丢失。 原因:第4步中乙事务修改A并写回后覆盖了甲事务的修改 并发操作带来的数据不一致性(不正确性) 丢失修改(Lost Update) 不可重复读(Non-repeatable Read) 读“脏”数据(Dirty Read) 记号 R(x):读数据x W(x):写数据x 两个事务T1和T2读入同一数据并修改,T2的提交结果破坏了T1提交的结果,导致T1的修改被丢失。 上面飞机订票例子就属此类
不可重复读是指事务T1读取数据后,事务T2
    执行更新操作,使T1无法再现前一次读取结果。

不可重复读包括三种情况:
(1)事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时,得到与前一次不同的值 

不可重复读

(2)事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录消失了
(3)事务T1按一定条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录。
后两种不可重复读有时也称为幻影现象(Phantom Row)

读“脏”数据

读“脏”数据是指:
事务T1修改某一数据,并将其写回磁盘
事务T2读取同一数据后,T1由于某种原因被撤销
这时T1已修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致
T2读到的数据就为“脏”数据,即不正确的数据
数据不一致性:由于并发操作破坏了事务的隔离性
并发控制就是要用正确的方式调度并发操作,使一个用户事务的执行不受其他事务的干扰,从而避免造成数据的不一致性

并发控制的主要技术
封锁(Locking)
时间戳(Timestamp)
乐观控制法
商用的DBMS一般都采用封锁方法

封锁(Locking)

并发控制的主要技术
封锁(Locking)
时间戳(Timestamp)
乐观控制法
商用的DBMS一般都采用封锁方法

一个事务对某个数据对象加锁后究竟拥有什么样的控制由封锁的类型决定。
基本封锁类型
排它锁(eXclusive Locks,简记为X锁)
共享锁(Share Locks,简记为S锁)

排它锁又称为写锁
若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁
保证其他事务在T释放A上的锁之前不能再读取和修改A

共享锁又称为读锁
若事务T对数据对象A加上S锁,则其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁
保证其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改

在锁的相容矩阵中:
最左边一列表示事务T1已经获得的数据对象上的锁的类型,其中横线表示没有加锁。
最上面一行表示另一事务T2对同一数据对象发出的封锁请求。
T2的封锁请求能否被满足用矩阵中的Y和N表示
Y表示事务T2的封锁要求与T1已持有的锁相容,封锁请求可以满足
N表示T2的封锁请求与T1已持有的锁冲突,T2的请求被拒绝

活锁和死锁

封锁技术可以有效地解决并行操作的一致性问题,但也带来一些新的问题
死锁

事务T1封锁了数据R1
T2封锁了数据R2
T1又请求封锁R2,因T2已封锁了R2,于是T1等待T2释放R2上的锁
接着T2又申请封锁R1,因T1已封锁了R1,T2也只能等待T1释放R1上的锁
这样T1在等待T2,而T2又在等待T1,T1和T2两个事务永远不能结束,形成死锁 

两类方法
1. 预防死锁
2. 死锁的诊断与解除

活锁

事务T1封锁了数据R
事务T2又请求封锁R,于是T2等待。
T3也请求封锁R,当T1释放了R上的封锁之后系统首先批准了T3的请求,T2仍然等待。
T4又请求封锁R,当T3释放了R上的封锁之后系统又批准了T4的请求……
T2有可能永远等待,这就是活锁的情形 

避免活锁:采用先来先服务的策略
当多个事务请求封锁同一数据对象时
按请求封锁的先后次序对这些事务排队
该数据对象上的锁一旦释放,首先批准申请队列中第一个事务获得锁

死锁的预防

产生死锁的原因是两个或多个事务都已封锁了一些数据对象,然后又都请求对已为其他事务封锁的数据对象加锁,从而出现死等待。
预防死锁的发生就是要破坏产生死锁的条件
预防死锁的方法
一次封锁法
顺序封锁法

要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行
存在的问题
降低系统并发度
难于事先精确确定封锁对象

顺序封锁法是预先对数据对象规定一个封锁顺序,按顺序编号,所有事务都按这个编号顺序申请封锁。
顺序封锁法存在的问题
维护成本
数据库系统中封锁的数据对象极多,并且在不断地变化。
难以实现:很难事先确定每一个事务要封锁哪些对象
结论
在操作系统中广为采用的预防死锁的策略并不很适合数据库的特点
DBMS在解决死锁的问题上更普遍采用的是诊断并解除死锁的方法

死锁的诊断
超时法

如果一个事务的等待时间超过了规定的时限,就认为发生了死锁
优点:实现简单
缺点
有可能误判死锁
时限若设置得太长,死锁发生后不能及时发现

事务等待图法

用事务等待图动态反映所有事务的等待情况
事务等待图是一个有向图G=(T,U)
T为结点的集合,每个结点表示正运行的事务
U为边的集合,每条边表示事务等待的情况
若T1等待T2,则T1,T2之间划一条有向边,从T1指向T2

并发控制子系统周期性地(比如每隔数秒)生成事务等待图,检测事务。如果发现图中存在回路,则表示系统中出现了死锁。

数据库 - 并发控制

标签:一致性   并发   控制   系统   数据库   

人气教程排行