在单片机系统中,事务的并发执行实际上是这些事务的并行操作轮流交叉执行
,这种执行方式称为交叉并发方式
多个事务真正的并行运行,这种并行执行方式称为同时并发方式。
事务是并发控制的基本单位
,保证事务ACID特性是事物处理的重要任务,而事务的ACID特性可能遭到破坏的原因之一是多个事务对数据库的并发操作造成的。为保证事务的隔离性和一致性,数据库管理系统要对并发操作进行正确调度。
这就是数据库管理系统中并发控制机制的责任。
并发操作带来的数据不一致包括丢失修改、不可重复读、读“脏”数据。
丢失修改
:两个事务T1和T2读入同一数据并修改,T2提交的结果破坏了T1提交的结果,导致T1的修改被丢失
不可重复读
:事务T1读取数据后,事务T2执行更新操作使T1无法再现前一次读取结果。具体讲有三种情况:
(1)事务T1读取某一数据后,事务T2对其进行了修改,当事务T1再次读取该数据时,得到与前一次不同的值
(2)事务T1按一定条件读取某些数据记录后,事务T2删除其中部分记录,当T1再次按相同条件读取数据时,发现某些记录神秘消失了
(3)事务T1按一定条件读取某些数据记录后,事务T2插入一些记录,当T1再次按相同条件读取数据时,发现多了一些记录
读“脏”数据
:事务T1修改某一数据将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤销,这是被T1修改过的值恢复原值,T2读到的数据就与数据可中的不一致,则T2读到的数据就是“脏”数据,即不正确的数据
这三类数据不一致的主要原因:并发操作破坏了事物的隔离性
并发控制的主要技术:封锁
、
封锁
:事务T在对某个数据对象操作前,先向系统发出请求,对其加锁
。
加锁后事务T就对该数据对象有了一定控制,在事务T释放它的锁之前,其他事务不能更新此数据对象。
确切控制由封锁的类型决定
基本封锁类型:排他锁
、共享锁
排他锁(写锁、X锁)
:事务T对对象A加X锁后,只允许T读取和修改A,其他事物都不能再对A加任何类型的锁,直到T释放。
共享锁(读锁、S锁)
:事务T对对象A加S锁后,T可以读取A但不能修改A,其他事物只能对A加S锁,不能加X锁,直到T释放。
运用X锁和S锁时,约定一些规则,如:何时申请X锁或S锁、持锁时间、何时释放等。这些规则称为封锁协议
一级封锁协议
:事务T再修改数据R之前必须对其加X锁,直到事务结束释放。
可防止丢失修改,不能防止不可重复读、读“脏”数据
二级封锁协议
:在一级封锁协议的基础上,增加事务T在读取数据R前先对其加S锁,读完即可释放
S锁
可防止丢失修改、读“脏”数据,不能防止不可重复读
三级封锁协议
:在一级封锁协议的基础上,增加事务T在读取数据R前先对其加S锁,直到事务结束才释放
S锁
可防止丢失修改、读“脏”数据、不可重复读
和操作系统类似。
事务T可能永远等待,这就是活锁
的情形
避免活锁的简单方法是采用先来先服务的策略
事务T1等待T2,T2有等待T1,T1和T2两个事务永远不能结束,形成死锁
1.死锁的预防
一次封锁法:要求每个事务一次将要使用的所有数据加锁,否则不能继续执行
顺序封锁法:预先对数据对象规定封锁顺序,事务都按这个顺序实施封锁
2.死锁的诊断与解除
超时法:一个事物等待时间超过了规定时限,就认为发生了死锁
等待图法:每个结点表示正运行的事务,边表示事务等待情况,如果发现图中存在回路,则发生死锁
一旦死锁,要设法解除,通常采用:选择一个处理死锁代价最小的事务,将其撤销,释放其持有的锁,使其他事务得以继续运行
什么样的调度是正确的?显然,串行调度是正确
的。执行结果等价于串行调度的调度也是正确的。
多个事务并发执行是正确的,当且仅当
其结果与按某一次串行
的执行这些事务时的结果相同,称这种调度策略为可串行化调度
可串行性
是并发事务正确调度的准则
例:
事务T1:读B;A=B+1;写回A;
事务T2:读A;B=A+1;写回B;
为保证并发调度的正确性,数据库管理系系统的并发控制机制必须提供一定手段保证调度是可串行化的。目前数据库管理系统普遍采用两段锁协议
两段锁协议
:所有事务必需分两个阶段对数据项加锁和解锁
说明
:
事务遵守两段锁协议是可串行化调度的充分条件
如并发事务都遵守两段锁协议,则这些事务的任何并发调度策略都是可串行化的;但若并发事务的一个调度是可串行化的,不一定所有事务都符合两段锁协议。
两段锁协议和防止死锁的一次封锁法的区别
:
一次封锁法要求每个事务必须一次将所有要使用的数据全加锁,否则不能执行,因此一次封锁法是遵守两段锁协议的;但两段锁协议并不要求事务必须一次将所有要使用的数据全加锁,因此遵守两段锁协议的事务可能发生死锁
。
《数据库系统概论》