数据库中日志问题详解
2009-04-24 13:12:45 来源:WEB开发网恢复管理的第一个任务就是将事务划分为已经提交事务和未提交事务。如果在日志中,根据undo的规则2,事务T所做的全部改变在此之前已经写到磁盘上,因此当故障发生时,该事务T不可能导致数据库的不一致状态。
然而,假设在日志中,只有记录,而没有与之相匹配的记录。那么就有可能在崩溃前,事务的某些修改已经反应到磁盘上,而另外一些修改可能未发生或者还在缓冲区中。这种情况下,T是一个未完成的事务,因为必须被撤消。也就是说,T所做的任何修改都必须恢复为原来的值。Undo的规则1使该想法可以成为可能,因为在修改数据刷盘之前,日志文件中已经保存了修改数据的原先值。对于,只需要将X的值恢复为v就行了(我们不必检查数据库中X现有值是否为v)。
日志中可能有一些未提交的事务,并且甚至可能有一些未提交的事务修改了X,所以恢复时采用从日志文件尾向前扫描。在扫描过程中记住所有有或记录的事务T。同时在随后的扫描中,如果它看见,则:
1) 如果T的COMMIT记录已被扫描到,则什么也不做。
2) 否则,将数据库中元素X的值改为v。在做完这些操作后,为以前未中止且未完成的每个事务T写入一个日志记录,然后刷新日志。
对于表2,作如下分析:
1)崩溃在第12步后发生。因为日志记录已经写入日志文件。当恢复时,不需要处理T事务。
2)崩溃发生在11步和12步之间。日志中记录了三条记录:、以及。当恢复管理进行向后扫描时,首先遇到记录,于是它将B在磁盘上的值存为500。接着它遇到记录,于是它将A在磁盘上的值存为1000。最后记录被写到日志中且日志被刷新。
3)崩溃发生在第8步和第11步之间。情况2一样。
4)崩溃发生在第8步之前。日志系统中只有一条记录:。记录被写到日志中且日志被刷新。(实际上,在实际系统中,可能其他的事务执行FLUSH LOG操作,而将事务T的日志记录写入磁盘中,如果是这样的话,日志中可能已经写入和,对于这种情况,执行情况2的恢复就行。实际上这些细节不影响undo的恢复效用,为了简单起见,忽视这些情况)。
5.静态检查点
正如我们所看到的那样,恢复时需要检查整个日志。当采用undo类型的日志时,一旦日志记录被写入日志文件,事务T的日志记录就可以忽视了。但是此时事务T却不能截断日志,因为事务是交替执行的,如果这时将日志截断,可能丢失活动着的事务的日志记录
解决该问题的方法是周期性地对日志做检查点。步骤如下:
1)停止接受新的事务
2)等待所有当前的活动事务提交或终止,并且在日志文件中写COMMIT或ABORT记录。
3)将日志刷新到磁盘
4)写入日志记录,并再次刷新记录。
5)重新开始接受新事务。
当恢复事,扫描到日志时,就不需要继续扫描日志记录了。
例如:假设日志开始时是这样的:
这时候,我们做一个检查点。等待事务T1和事务T2都完成,才在日志文件中写记录。检查点做完后,可以接受新的事务,这里为事务T3,T3执行了一些操作,此时系统崩溃了。
恢复时,从文件尾部开始扫描,因为T3是未完成事务,则将磁盘上F的值存为前值30、磁盘上E的值存为前值25。当扫描到日志记录时,我们知道没有必要检查以前的日志记录了,并且数据库状态的恢复已经完成。
更多精彩
赞助商链接