并发操作带来的数据不一致性
(1)丢失修改
丢失修改是指事务1与事务2从数据库中读入同一数据并修改,事务2的提交结果破坏了事务1提交的结果,导致事
务1的修改被丢失。
(2)不可重复读
不可重复读是指事务1读取数据后,事务2执行更新操作,使事务1无法再现前一次读取结果
三类不可重复读:
a)事务2对其做了修改,当事务1再次读该数据时,得到与前一次不同的值;
b)事务2删除了其中部分记录,当事务1再次读取数据时,发现某些记录神奇的消失了
c)事务2插入了一些记录,当事务1再次按相同条件读取数据时,发现多了一些记录。
后两种不可重复读有事也被称为幻影(phantom row)

(3)读“脏”数据

事务1修改某一数据,并将其协会磁盘,事务2读取同一数据后,事务1由于某种原因被撤回。这时事务1已经修改


过的数据恢复原值,事务2读到的数据就与数据库不一致,是不正确的数据,又被称为“脏读”


产生上述不一致性的原因:


并发操作破坏了事务的隔离性,引发了数据的不一致性


解决办法:


采用封锁机制


基本封锁类型


DBMS通常提供了多种类型的封锁。一个事务对某个数据对象加锁后究竟拥有什么样的控制石油封锁的类型决定的。


排它锁(简记为X锁)


若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能对A加任何类型的锁,直到T释放A上的锁。


共享锁(简记为S锁)


若事务T对数据对象A加上S锁,则其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁




两段锁协议


事务分为两个阶段


第一阶段是获得封锁,也称为扩展阶段


第二阶段是释放封锁,也称为收缩阶段



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


活锁


由于系统调度的原因,某些事务的加锁请求得不到响应而永远等待下去,称为活锁。


解决办法


采用合理的调度方法,如先来先服务(FCFS)策略。


死锁


两个或多个事务都已封锁了一些数据对象,然后又都请求对已被其他事务封锁的数据对象加锁,从而出现死等待


解决办法:


(1)预防死锁


一次封锁法:


要求每个事务必须一次将所有要使用的数据全部加锁,否则就不继续执行。


顺序封锁法


顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序进行封锁。


(2)诊断与解除死锁


在操作系统中广为采用的预防死锁的策略并不适合数据库的特点,DBMS在解决死锁的问题上更普遍采用的是诊断并解除死锁的方法。


超时法:


如果一个事务的等待时间超过了规定的权限,就认为发生了死锁。


等待图法:


用事务等待图动态反应所有事务的等待情况。


事务等待图是一个有向图G=(T,U)


T为节点的集合,每个节点表示正运行的事务


U为边的集合,每条边表示事务等待的情况


若T1等待T2,则T1,T2之间画一条有向边,从T1指向T2


并发控制子系统周期性的检测事务等待图,如果发现图中存在回路,则表示系统中出现了死锁。


解除死锁:选择一个处理代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其他事务能够继续运行下去。