关于检查点队列、检查点位置我们先说到这里,在全面的介绍什么是增量检查点之前,我们先说一下检查点队列的一个重要作用。 让我们先来总结一下用户修改块时,Oracle内部都发生了什么: 1.如果块不在Buffer cache,将块读入Buffer cache 2.先生成重做记录,并记入日志缓存,在用户提交时写到日志文件中 3.在Buffer cache中修改块 4.在Buffer cache中设置块的脏标志位,标志块变成脏块,同时在检查点队列末尾增加一个新节点,记录这个新脏块的信息,信息包括:脏块在Buffer cache中的位置,在步骤2时生成的与此脏块对应的重做记录位置。 5.用户提交后,将相应的重做记录从重做缓存写入日志文件。
我现在将日志补充到上面的图中: 
就像上图,检查点队列的每个节点,都保存有脏块的地址和脏块对应的重做记录的编号。脏块在Buffer cache中的位置是随机的,用户不一定修改那个块。但重做记录是顺序生成的,就和检查点队列的排列顺序一样。因为,它们都是当块被修改而变脏时产生的。块A先被修改,块A的重做记录就排在前面,块B后被修改,块B对应的重做记录会被排在块A对应的重做记录的后面。和它们在检查点中的顺序是一样。每当数据库因异外而当机,比如异常死机、断电等等,Buffer cache中有许多脏块没来的及写到磁盘上。以图为例,比如说现在断电了,现在磁盘上还有7个脏块,它们里面有用户修改过的数据,Oracle已经将反馈信息“你的修改完成”发送给用户,用户也以为他们的修改完成了,将为一直保存到数据库中。但是,断然的断电,令这几个脏块中的数据丢失了,它们没来得及写到磁盘上。 Oracle如何解决这个问题呢?很简单,当数据库重新启动时,Oracle只需从控制文件中读出检查点位置,检查点位置中记录有重做记录编号,根据此编号,Oracle可以很快的定位到日志文件中的重做记录n,它读出重做记录n中的重做数据,将用户的修改操作重现到数据库。接着,Oracle读取重做记录n+1中的重做数据,重现用户修改,这个过程将沿着日志流的顺序,一直进行下去,直挡最后一条重做记录,在上图的例子中,最后一条重做记录是第n+6条。这个过程完成后,用户所有的修改又都被重现了,一点都不会丢失。只要你的日志文件是完整,日志流是完整的,就一点信息都不会丢失。 有人可能会有一个问题,重做记录在生成后,也是先被送进重做缓存,再由重做缓存写往日志文件。这样的机制下,一定会有某些重做记录在没来的及写到日志文件中时,数据库突然当机,而造成这些重做记录丢失。这样,这些重做记录所对应的脏块,将得不到恢复。用户还是会丢失一些数据。 这种情况的确会发生,但丢失的都是没用的信息。为什么这么说的。Oracle会在用户每次发出提交命令时,将事务所修改脏块对应的重做记录写进日志文件,只有当这个操作完成时,用户才会收到“提交完成”,这样的信息,对于一个完整的事务,当用户看到提交完成后,也就意味着所对应的重做记录一定被写到了日志文件中,即使发生异常死机,它也是绝对可以恢复。而当用户没有提交,或没来得及提交,数据库就崩溃了,那么事务就是不完整的,这个事务必须被回滚,它根本用不着恢复。对于这样不完整的事务,它对应的重做记录有可能丢失,但这无所谓了,因为不完整的事务根本不需要恢复。也就是说,只有用户的事务提交了,用户的修改一定不会丢失。不过这还有一个前提,就是日志文件千万不能损坏,DBA所要做的就是要保证日志文件不能损坏。DBA可以使用RAID1这样的磁盘镜像技术,或者多元备份日志文件,等等,这个我们在前面章节中已经讲过了的。 我们上面所讲到的这种恢复,是自动进行的,并且不需要DBA参与,它被称之为实例恢复。 检查点队列与增量检查点的作用我们已经说的差不多了,它们的主要目的就是让DBWn沿检查点队列的顺序刷新脏块。还有,就是实例恢复。 |