oracle 的redo 机制db的一个重要机制,理解这个机制对dba来说也是非常重要,之前的blog里也林林散散的写了一些,前些日子看老白日记里也有说明,所以结合老白日记里的内容,对oracle 的整个redo log 机制重新整理一下。
一.redo log 说明oracle 的online redo log 是为确保已经提交的事务不会丢失而建立的一个机制。 因为这种健全的机制,才能让我们在数据库crash时,恢复数据,保证数据不丢失。
1.1 恢复分类恢复分两种:
(1) crash recovery
(2) media recovery
这两种的具体说明,参考:
oracle 实例恢复时 前滚(roll forward) 后滚(rollback) 问题
这两种的区别是:
(1) crash recovery 是在启动时db 自动完成,而mediarecovery 需要dba 手工的完成。
(2) crash recovery 使用online redo log,media recovery 使用archived log 和 online redo log。
(3) media recovery 可能还需要从备份中restore datafile。
1.2 crash recovery 过程 当数据库突然崩溃,而还没有来得及将buffer cache里的脏数据块刷新到数据文件里,同时在实例崩溃时正在运行着的事务被突然中断,则事务为中间状态,也就是既没有提交也没有回滚。这时数据文件里的内容不能体现实例崩溃时的状态。这样关闭的数据库是不一致的。
下次启动实例时,oracle会由smon进程自动进行实例恢复。实例启动时,smon进程会去检查控制文件中所记录的、每个在线的、可读写的数据文件的end scn号。
数据库正常运行过程中,该end scn号始终为null,而当数据库正常关闭时,会进行完全检查点,并将检查点scn号更新该字段。
而崩溃时,oracle还来不及更新该字段,则该字段仍然为null。当smon进程发现该字段为空时,就知道实例在上次没有正常关闭,于是由smon进程就开始进行实例恢复了。
1.2.1 前滚 smon进程进行实例恢复时,会从控制文件中获得检查点位置。于是,smon进程到联机日志文件中,找到该检查点位置,然后从该检查点位置开始往下,应用所有的重做条目,从而在buffer cache里又恢复了实例崩溃那个时间点的状态。这个过程叫做前滚,前滚完毕以后,buffer cache里既有崩溃时已经提交还没有写入数据文件脏数据块,也还有事务被突然终止,而导致的既没有提交又没有回滚的事务所弄脏的数据块。
1.2.2 回滚 前滚一旦完毕,smon进程立即打开数据库。但是,这时的数据库中还含有那些中间状态的、既没有提交又没有回滚的脏块,这种脏块是不能存在于数据库中的,因为它们并没有被提交,必须被回滚。打开数据库以后,smon进程会在后台进行回滚。
有时,数据库打开以后,smon进程还没来得及回滚这些中间状态的数据块时,就有用户进程发出读取这些数据块的请求。这时,服务器进程在将这些块返回给用户之前,由服务器进程负责进行回滚,回滚完毕后,将数据块的内容返回给用户。
总之,crash recovery时,数据库打开会占用比正常关闭更长的时间。
1.2.3 必须先前滚,在回滚 回滚段实际上也是以回滚表空间的形式存在的,既然是表空间,那么肯定就有对应的数据文件,同时在buffer cache 中就会存在映像块,这一点和其他表空间的数据文件相同。
当发生dml操作时,既要生成redo(针对dml操作本身的redo entry)也要生成undo(用于回滚该dml操作,记录在undo表空间中),但是既然undo信息也是使用回滚表空间来存放的,那么该dml操作对应的undo信息(在buffer cache生成对应中的undo block)就会首先生成其对应的redo信息(undo block's redo entry)并写入log buffer中。
这样做的原因是因为buffer cache中的有关undo表空间的块也可能因为数据库故障而丢失,为了保障在下一次启动时能够顺利进行回滚,首先就必须使用redo日志来恢复undo段(实际上是先回复buffer cache中的脏数据块,然后由checkpoint写入undo段中),在数据库open以后再使用undo信息来进行回滚,达到一致性的目的。
生成完undo block's redo entry后才轮到该dml语句对应的redo entry,,最后再修改buffer cache中的block,该block同时变为脏数据块。
实际上,简单点说redo的作用就是记录所有的数据库更改,包括undo表空间在内。
1.2.4 crash recovery 再细分crash recovery 可以在细分成两种:
(1) 实例恢复(instancerecovery)
(2) 崩溃恢复(crashrecovery)
instancerecovery与crashrecovery是存在区别的:针对单实例(singleinstance)或者rac中所有节点全部崩溃后的恢复,我们称之为crash recovery。 而对于rac中的某一个节点失败,存活节点(surviving instance)试图对失败节点线程上redo做应用的情况,我们称之为instancerecovery。
不管是instance recovery还是crash recovery,都由2个部分组成:cache recovery和transaction recovery。
根据官方文档的介绍,cache recovery也叫rolling forward(前滚);而transaction recovery也叫rolling back(回滚)。
1.3 redo log 说明redo log 的数据是按照thread 来组织的,对于单实例系统来说,只有一个thread,对于rac 系统来说,可能存在多个thread,每个数据库实例拥有一组独立的redo log 文件,拥有独立的log buffer,某个实例的变化会被独立的记录到一个thread 的redo log 文件中。
