事务恢复
1.事务---一个数据库操作序列,是数据库应用程序的基本逻辑单元。这些操作要么都做,要么都不做,是一个不可分割的执行单位。
2.事务应具有的性质
- 原子性--事务执行时的不可分割性,即事务所包含的活动要么都做,要么不做
- 一致性--事务对数据库的作用应使数据库从一个状态到另一个状态
- 隔离性--多事务并发执行,应像各事务独立执行一样,不能相互干扰,一个正在执行的事务其中间结果不能为其他事务所访问
- 持久性--一旦事务提交,不论执行何种操作或发生何种故障,都不应对该事务的执行结果有任何影响
3.故障种类
- 事务内部故障----可以通过事务程序本身发现并处理的故障
- 系统范围内的故障(软故障)--造成系统停止任何事件,如CPU故障,操作系统故障,程序代码错误,断电等,使得系统必须重新启动
- 介质故障(硬故障)--如磁盘损坏,磁头碰撞,强磁场干扰等
- 计算机病毒
4.恢复的实现技术
数据库恢复的基本原理-----冗余
数据库恢复的机制
- 建立冗余数据(常用技术:数据转储,登记日志文件)
- 利用冗余数据实施数据库恢复
数据转储与恢复
转储:DBA定期将整个数据库复制到磁带或另一个磁盘上保存起来的过程
转储的状态:
静态转储--转储期间不允许对数据库进行操作
动态转储--转储期间允许对数据库操作
转储方式:海量转储(每次转储全部数据库),增量转储(只转储上次转储后更新过的数据)
恢复:当数据库被破坏后可将后备副本重新装入,并重新运行转储以后的所有更新事务
日志文件和恢复
日志--用来记录对数据库的更新操作的文件
日志文件的作用
静态转储:数据库毁坏后,重装后援副本,根据日志文件,重做已完成的事务,并撤销未完成的事务
动态转储:用后援副本和日志文件综合起来恢复数据库
登记日志文件原则:严格按并发事务执行的时间次序登记,先写日志文件,后写数据库
5.恢复策略(利用日志文件进行恢复)
基本策略:对于尚未提交的事务,执行撤销处理(UNDO)。对于已经提交的事务,执行重做处理(REDO)
基本方法:扫描日志文件,确定所有已经开始但尚未提交的事务(对它们需UNDO),再确定所有已提交的事务(对它们需REDO)
事务故障恢复:事务故障是指事务被非正常终止,应根据日志文件对未完成事务做UNDO处理,步骤如下:
(1)反向扫描日志文件,查找未完成事务的更新操作;
(2)对该事务的更新操作执行逆操作;
(3)继续反向扫描日志文件,对遇到的更新操作做同样处理;
(4)当遇到某事务的开始标记时,停止对该事务的处理。
系统故障恢复:系统故障造成数据库不一致的原因,一是未完成事务对数据库的更新已写入数据库,二是已提交事务的结果
在故障发生前留在缓冲区没来得及写入数据库。恢复操作是撤消未完成事务,重做已完成事务。步骤如下:
(1)正向扫描日志文件,找出在故障发生前己提交的事务,将它们记入重做(REDO)队列,同时找出故
障发生前尚未完成的事务,将它们记入撤消(UNDO)队列。
(2)反向扫描日志文件,对UNDO队列的每个事务执行逆操作,即做撤消处理。
(3)正向扫描日志文件,对REDO队列中的每个事务重新执行日志文件登记的操作。
介质故障恢复:介质故障发生后,磁盘上的数据文件和日志文件均被破坏,恢复的方法是重装数据库和日志文件,然后重做
自转储以来已完成的事务。步骤如下:
(1)装入最近转储的数据库后援副本,若是动态转储,则还应装入转储期间的日志文件,将数据库恢复到一致性状态。
(2)装入转储结束后的日志副本,重做已完成的事务。
6.具有检查点的恢复技术
具有检查点的恢复算法
- 根据重新开始文件中最后一个检查点记录的地址,在日志文件中找到最近的一个检查点记录;
- 设置两个队列,将检查点中的所有事务放入UNDO-LIST,并令REDO-LIST暂为空集;UNDO-LIST:需要UNDO操作的事务集合;
REDO-LIST:需要REDO操作的事务集合; - 从该检查点开始扫描日志文件到文件结束为止:凡遇有begin transaction的事务放入UNDO-LIST;凡遇有commit的事务,将它从UNDO-LIST移入REDO-LIST;
- 对UNDO-LIST中的事务执行UNDO操作,对REDO-LIST中的事务执行REDO操作
7.数据库镜像--将整个数据库或其中的关键数据同时存放在两个分离的物理磁盘上。每当主数据库更新时,DBMS自动把更新后的数据复制到另一个磁盘上,从而自动保证主数据库与镜像数据库的一致性。
数据库镜像的优点:可提高数据库的可用性。在介质故障时,不需关闭系统和重装后援副本,保证“不间断”地恢复;便于并发操作,当主数据库的某个对象被加排它锁时,其它应用可以读镜像数据库。
数据库镜像的缺点:由于频繁地复制数据,会降低系统的运行效率; 使用更多的磁盘设备。
事务并发
在多用户数据库系统中,当多个用户并发存取数据库时就会产生多个事务同时存取同一数据的情形。若不加控制,可能会存取和存储不正确的数据,造成数据库的不一致性。
并发操作带来的数据不一致性包括三类:
- 丢失修改---两事务读出同一数据并修改,先写回的数据修改丢失
- 三种情况可造成不可重复读:
(1)事务T1读取某一数据后,事务T2对其做了修改,事务T1再次读取该数据时,发现与前次不同;
(2)事务T1按一定条件读取了某些数据记录后,事务T2删除了其中的部分记录,事务T1再次按相同条件读取记录时,发现有些记录不存在;
(3)事务T1按一定条件读取了某些数据记录后,事务T2插入了一些记录,事务T1再次按相同条件读取记录时,发现多了一些记录。
- 读出“脏”数据---事务T1修改某一数据,事务T2读取同一数据,事务T1由于某种原因被撤销,则T2读到的就是“脏”数据
并发控制的技术---封锁(事务在修改某个对象前,先锁住该对象,不允许其他事务读取或者修改该对象,修改完毕或事务完成之后再将锁打开)
封锁类型
- 排他锁--若事务T对数据对象R加上X锁,则只允许T读、写R,禁止其它事务对R加任何锁,相应地其它事务就无法读、写对象R。
- 共享锁--若事务T对数据对象R加上S锁,则T可以读R,但不可以写R,且其它事务可以对R加S锁、但禁止加X锁。这
保证了事务T在释放R的S锁之前,其它事务只可以读R,不可以修改R。
封锁协议
- 1级封锁协议--事务T在修改数据对象R之前必须先对其加X锁,直到事务结束才释放。
- 1级封锁协议作用--防止丢失修改
- 2级封锁协议--1级封锁协议+事务T在读取数据对象R之前必须先对其加S锁,读完即释放S锁。
- 2级封锁协议作用--防止丢失修改,防止读“脏”数据
- 3级封锁协议--1级封锁协议+事务T在读取数据对象R之前必须先对其加S锁,S锁也是直到事务结束才释放。
- 3级封锁协议作用--防止丢失修改,防止读“脏”数据,保证可重复读
活锁--数据对象不断处于上锁、开锁的交替状态,某个事务有可能为该对象上锁,但始终没有得到上锁机会而永久等待下去的情形。
避免活锁--如采用先来先服务策略
死锁--多个事务因封锁冲突(竞争资源)而永远等待下去的情形
死锁问题的解决方法
预防死锁--一次封锁法(每个事务必须将所要求的数据对象全部上锁后才能执行读写操作,否则释放占用的资源),顺序封锁法(对所有数据对象规定一个封锁顺序,所有事务均按这个顺序实行封锁)
诊断死锁并解除--超时法(当一个事务的等待时间超过了规定的时限,就认为发生了死锁),等待图法(用一个有向图表示事务等待的情况。图中节点表示事务,边表示事务间的等待关系。并发控制子系统定时检查此图,若发现有回路,则产生死锁)
可串行化调度--多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些这些事务时的结果相同
两段锁协议
(1)在对任何数据进行读、写操作之前,事务首先要申请并获得对该数据的封锁(读时S锁,写时X锁)
(2)在释放一个封锁之后,事务不再申请和获得新的封锁。