在数据库系统中日志是记录数据库修改的结构,记录数据库中的所有更新活动。描述一次数据库写操作的一个更新日志记录包含如下几个字段:
1)事务标识符是执行write操作事务的唯一标识符。
2)数据项标识符是所写数据项的唯一标识符。通常是数据项在磁盘上的位置。
3)旧值是写之前数据项的值。
4)新值是写之后数据项的值。
每次事务执行写操作之前,必须在数据库修改前建立该次写操作的日志记录。一旦日志记录已存在,如果需要,就可以输出对数据库的修改,并且,我们能够利用日志记录中的旧值字段来撤销已经对数据库的修改。
为了从系统故障和磁盘故障中恢复时能使用日志记录,日志必须放在稳定存储器上。利用日志,系统可以解决任何不造成非易失性存储器上的信息丢失的故障。
恢复机制使用两个恢复过程:
1)undo(Ti)将事务Ti所更新的所有数据项的值恢复成旧值。
2)redo(Ti)将事务Ti所更新的所有数据项的值置为新值。
Ti所更新过的数据项集合及其旧值和新值均能在日志中找到。
故障发生后,恢复机制检查日志,决定哪些事务需要redo,哪些需要undo:
事务Ti需要undo,如果日志包含记录<Ti start>,但不包含记录<Ti commit>。
事务Ti需要redo,如果日志即包含记录<Ti start>,又包含记录<Ti commit>。
数据库系统中的检查点相关操作
当系统发生故障时,必须检查日志,决定哪些事务需要redo,哪些事务需要undo。
系统周期性地执行检查点(checkpoint),需要执行下列动作序列:
1.将当前位于主存的所有日志记录输出到稳定的存储器上。
2.将所有修改了的缓冲块输出到磁盘上。
3.将一个日志记录<checkpoint>输出到稳定存储器。
检查点执行过程中,不允许事务执行任何更新动作,如写缓冲块或写日志记录。
日志记录<checkpoint>使系统提高了恢复过程的效率。
例如在检查点前提交的事务Ti。记录<Ti commit>在日志中出现在<checkpoint>前。Ti所最的任何数据库修改都必然已在检查点前或作为检查点本身的一部分写入数据库。因此,在恢复时就不必再对Ti执行redo操作了。
故障发生后,恢复机制检查日志来确定最近的检查点发生前开始执行的最近一个事务Ti。
要找到这个事务只需要从日志的尾部有后之前搜索日志,直到找到第一个<checkpoint>记录(由于由后至前搜索,这个找到的记录是日志中的最后一个<checkpoint>记录),然后继续向前搜索直至发现下一个<Ti
start>记录。该记录指明了事务Ti。
一旦系统确定事务Ti,则只需要对事务Ti和事务Ti后开始执行的所有事务Tj执行redo和undo操作。日志的剩余部分(前面的部分)可以忽略,并且可以根据需要随时删除。
并发事务的恢复
在并发事务处理系统中,检查点日志记录的形式<checkpoint L>,其中L为检查点是活跃的事务列表。
当系统从崩溃中恢复时,它构造两个列表:undo-list由需要撤销的事务构成,redo-list由需要重做的事务构成。
两个列表按如下步骤构造:开始时都为空。系统有后至前扫描日志,检查每一条记录,直至发现第一个<checkpoint>记录:
对每个<Ti commit>的记录,将Ti 加入redo-list.
对每个<Ti start>的记录,如果Ti不属于redo-list,则将Ti加入undo-list。
所有相应的日志记录都检查后,系统查看检查点记录中的列表L。对L中的每一个事务Ti,
如果Ti不属于redo-list,则将Ti加入undo-list。
redo-list,undo-list构造完,恢复过程进行如下工作:
1.系统从最近一个记录开始由后至前重新扫描日志,并且对undo-list中事务Ti的每一个日志记录执行undo操作。redo-list中事务的日志记录在本步骤中忽略。当undo-list中的所有事务 Ti
所对应的<Ti start>记录都找到时,扫描停止。
2.系统找出日志中的最近一条<checkpoint L>记录。上一步已经经过了最近的检查点记录,这一步可能要由前至后扫描日志。
3.系统有最近一条<checkpoint L>记录开始有前至后扫描日志,并且对redo-list中事务Ti的每一个日志记录执行redo操作。这时忽略undo-list中事务的日志记录。
当undo-list中的所有事务撤销后,重做redo-list中的事务。由前至后处理日志。
当恢复过程完成时,事务处理恢复执行。