一、数据库恢复-事务故障
系统通过对事物进行UNDO操作和REDO操作可实现故障后的数据库状态恢复
1、对于发生事务故障后的数据库恢复
- 恢复机制在不影响其他事务运行的情况下,强行回滚夭折事务,对该事务进行UNDO操作,来撤销该事务已对数据库进行的更新,使得该事务好像根本没有执行过一样,从而保持事务的原子性
- 恢复是由DBMS自动完成的 ,对用户是透明的
2、基于这里给出的一段多事务并发执行的日志示意图,记录的表示应采用约定好的表示方法。
假设事务T1在生成更新好的日志记录后发生故障,则系统进行恢复的步骤如下:
(1)首先从日志尾部开始反向向前扫描日志,即从最近写的日志记录到最早写的日志记录,查找该事物的更新操作W1
(2)然后依次对该事务的所有更新操作执行逆操作,将更新记录中对某数据项更新前的值,如Xold Yold写入数据库。若该更新操作是插入操作,更新前的值应为空,恢复时相当于做删除操作。若该更新操作是删除操作,恢复时相当于做插入操作
(3)继续反向扫描日志,直至遇到标记此事务开始的日志记录B1,恢复过程终止,并在该事务中添加该事物的异常终止记录A1
对于日志从后向前反向扫描处理可保证最后恢复的数据是事务开始时的数据。在某些DBMS中,恢复操作对数据库的更新操作也可能会产生另一种形式的日志信息记载在日志中,但这些日志信息不会再用于恢复操作
二、数据库恢复-系统故障
1、对于发生系统故障后的数据库恢复
- 恢复机制在系统重新启动时利用日志撤销(UNDO)所有非正常终止的事务已对数据库进行的更新 。保持夭折事务的原子性
- 重做(REDO)已提交事务对数据库的更新,保持提交事务的持久性,从而将数据库恢复到发生故障前的一致性状态
- 系统故障的恢复是由DBMS在系统重新启动时自动完成的,不需要用户干预
基于这里给出的一段并发事务日志示意图,假设系统在事务T1生成更新记录后崩溃
则系统进行恢复的步骤如下(系统故障后的恢复算法)
(1)首先从日志头部开始向后正向扫描日志,即从最早写的日志记录到最近写的日志记录,找到故障发生前已提交的事务和未执行完的事务即夭折事务。
对于在日志中有Commit日志记录的已提交事务T2 T4,将其事务标识记入待重做事务队列REDO-LIST中,由于系统提交生成Commit日志记录时,并不能确定其对数据库的更新已经在磁盘上,重做就是让已提交事务对数据库所做的任何更新都反应到磁盘上。对于日志中只有Begin Transaction日志记录而无相应Commit日志记录的尚未完成的事务T1、T3和T6,即事务的最后一条日志记录是更新日志时,将其事务标识记入UNDO-LIST中,对于有Abort日志记录的T5,因该事务已在系统崩溃前被回滚,则不再对其进行恢复
(2)从日志尾部向前反向扫描日志,对撤销事务队列中的所有需撤销的事务的更新操作依次执行其逆操作,将更新记录中“更新前的值 ”写入数据库,最终完成对每个需撤销事务的回滚并生成其异常终止记录。
由于系统崩溃前可能有多个未提交的事务,其中某些事务可能均对某个数据对象比如X进行了更新,所以恢复操作的顺序必须是从日志尾部向前反向进行,以保证最终恢复的数据库中的X值是所有夭折事务开始执行前的值
(3)第三步是从日志头部向后正向扫描日志,对重做队列中每个需重做的事务重新执行日志中的更新操作,将更新记录中“更新后的值”写入数据库,恢复操作的顺序是必须从日志头部向后正向执行,保证对一个特定数据对象的多个更新的执行顺序,与系统崩溃前的执行顺序一致
虽然前面的恢复策略为了提高效率,在撤销事务或重做事务的过程中,并没有把不同事务的撤销或重做分开进行,而是对日志进行一次扫描,在扫描的过程中每遇到一个更新记录,就执行一次UNDO或REDO操作
2、系统故障后的恢复算法存在的问题
- 但不管日志有多长,恢复过程都要扫描整个日志,检查所有日志记录,来确定哪些事务需要撤销,哪些事务需要重做
- 此外,重做事务队列中的许多事务,实际上已经早把它们的更新操作结果写到磁盘的数据库中了,然而恢复机制又重新执行了对数据库的更新
为了解决这两个问题,许多DBMS,如SQL Server采用一种检查点技术实现系统故障的恢复
3、采用检查点技术实现系统故障后的恢复
(1)可以限制恢复过程必须回溯的日志长度,有效减少搜索日志的时间
(2)同时有效减少系统重新启动后需要重做的事务,从而减少数据库恢复所需的时间和资源
(3)检查点的设置
- 采用检查点技术的DBMS,其事务处理的恢复机制在系统运行过程中,要定期或不定期地在生成的日志上设置检查点,如每隔一个小时建立一个检查点
- 或按照某种规则建立检查点,如活动日志已写满一半时设置一个检查点
假设系统运行时在tc时刻设置了一个检查点,而在下一个检查点到来之前的tf时刻系统发生崩溃
则此时系统中的事务可分为五类状态的事务,T1类为在检查点之前已提交的事务,T2类为在检查点之前开始执行,在检查点之后故障点之前已提交的事务,T3类为在检查点之前开始执行,在故障点时还未完成的事务,T4类为在检查点之后开始执行,在故障点之前已提交的事务,T5类为在检查点之后开始执行,在故障点时还未完成的事务
系统出现故障后,恢复机制将根据事务的状态,采取不同的恢复操作,这里我们介绍一种基于静态检查点技术实现系统故障恢复的策略
4、采用静态检查点技术实现系统故障后的恢复
(1)恢复机制采用该技术在设置检查点时具体要完成的工作有
- 首先暂时终止运行事务的执行。系统不再执行对数据库的更新,也不产生新的日志记录
- 将当前日志缓冲区中的所有日志记录写入磁盘的日志中
- 在日志中写入一个检查点记录。检查点记录的内容至少要包括设置检查点时刻所有正在执行的事务
- 将当前数据缓冲区中的所有数据写入磁盘的数据库中
- 把检查点记录在日志中的地址写入一个重新开始文件
- 最后,完成上述操作后,重新开始执行运行的事务
根据系统在检查点所做的工作,可以确定T1类已提交事务不必重做,因为其对数据库的所有更新,如W1操作的结果,已在检查点tc时刻写到数据库中了。T2、T4类事务需要重做,因为它们对数据库的更新结果可能仍在内存缓冲区中,还未写到磁盘的数据库中,但是重做T2类事务时并不需要重做早于检查点记录的更新操作,如W2,因为这类操作对数据库的更新结果,已在设置检查点时被刷新到磁盘上,T3、T5类事务必须撤销,因为它们还未提交,在系统崩溃前它们对数据库的更新,如W5操作的结果可能已写到磁盘的数据库中,其中T3事务,其在检查点前对数据库进行的更新,如W3操作的结果,在设置检查点时就已写入数据库中了,这些更新操作的结果都必须撤销,
5、采用静态检查点技术实现系统故障后的恢复步骤
系统确定恢复的事务及其恢复操作可如下进行
(1)从重新开始文件中找到系统崩溃前最后一个检查点记录在日志中的地址,由该地址在日志中找到最后一个检查点记录
(2)从检查点记录得到设置检查点时刻所有正在执行的事务,将其放入撤销事务队列UNDO-LIST中,包括T2、T3类事务
(3)从检查点记录开始向后正向扫描日志,确定需要重做或撤销的事务
如有新开始的事务,即发现事务的BEGIN TRRANSACTION日志记录,如B4,把T4暂时放入撤销事务队列UNDO-LIST里,如有新提交的事务,即发现事务的COMMIT日志记录,如C2,把T2从撤销事务队列UNDO-LIST中移到重做事务队列REDO-LIST中,扫描日志直到日志结束,即系统崩溃处,当日志扫描结束时,撤销事务队列UNDO-LIST和重做事务队列REDO-LIST就分别是需要撤销的事务,如事务T3、T5,以及需要重做的事务,如事务T2、T4
(4)从日志尾部向前反向扫描日志,对撤销事务队列中的每个事务执行撤销(UNDO)操作
(5)从检查点开始正向扫描日志,对重做事务队列的每个事务执行重做(REDO)操作
这里介绍的检查点技术在设置检查点时不允许事务对缓冲区或日志进行任何更新,事务执行必须停下,这一要求对许多应用系统是不能接受的。因此,有的DBMS采用更复杂或效率更高的检查点技术,策略中也可能先执行重做操作等,在此不作进一步讨论
三、数据库恢复-介质故障
1、对于发生介质故障的数据库恢复
- 不仅要使用日志,还要利用数据转储得到的数据库备份。数据库备份保存数据库在转储时的状态,当数据库所在磁盘被损坏后,可首先利用最新的数据库备份,将数据库恢复到进行转储前的数据库状态
- 然后再利用日志备份将数据库恢复到离故障发生时最近的一致性状态
- 介质故障的恢复,需要数据库管理员DBA的介入,需要DBA装入最新转储的数据库备份和有关的日志文件备份,然后执行系统提供的恢复命令,具体的恢复操作仍由DBMS来完成
2、例如SQL Server支持的T-SQL语言提供可实现对数据库进行恢复的RESTORE DATABASE语句
(1)该语句可指定备份中要恢复的数据文件名或包括多个数据文件的文件组名
(2)需指定备份文件所在的存储路径
(3)可指定本次是否撤销备份中任何未提交的事务,使数据库处于某个一致性状态,一般只在系列恢复操作的最后一个操作选用RECOVERY选项,其他恢复操作选择NORECOVERY
(4)还可指定是否对数据库中同名数据库进行覆盖
四、小结
1、恢复就是把数据库从事务故障、系统故障和介质故障等造成的不一致错误状态恢复到某个已知的正确状态。主要是利用存储在日志和数据备份中的冗余数据撤销(UNDO)夭折事务已对数据库进行的更新,重做(REDO)已提交的事务。采用尽可能高效的恢复策略,对发生故障后的数据库进行恢复。
2、事务处理的恢复机制使得发生故障后事务的执行仍保持原子性和持久性,从而也保持了数据库的一致性状态