1、前滚和回滚介绍
“前滚和回滚”是Oracle数据库实例发生意外崩溃,重新启动的时候,由SMON进行的自动恢复过程。
因为oracle是先把操作命令写到 SGA的log buffer中,然后修改 数据;因此发生故障时,日志中的对数据库修改的记录其实是已经生效的;因此 SMON进程会把日志中的数据重新检查:先前滚,从redo log中找到checkpoint,从checkpoint开始,把已经commit的数据,岸顺序重新加载;直到找到日志中有记录,但是没有commit提交到redo log中的数据(此时就是故障发生的时间点了),然后根据这些日志的获取undo记录,进行回滚;
//undo是针对那些你没有commit的东西进行回滚的
当数据库突然崩溃,而还没有来得及将buffer cache里的脏数据块刷新到数据文件里,同时在实例崩溃时正在运行着的事务被突然中断,则事务为中间状态,也就是既没有提交也没有回滚。这时数据文件里的内容不能体现实例崩溃时的状态。这样关闭的数据库是不一致的。
下次启动实例时,Oracle会由SMON进程自动进行实例恢复。实例启动时,SMON进程会去检查控制文件中所记录的、每个在线的、可读写的数据文件的END SCN号。
数据库正常运行过程中,该control file中的END SCN号始终为NULL,而当数据库正常关闭时,会进行完全检查点,并将检查点SCN号更新该字段。
而崩溃时,Oracle还来不及更新该字段,则该字段仍然为NULL。当SMON进程发现该字段为空时,就知道实例在上次没有正常关闭,于是由SMON进程就开始进行实例恢复了。
下面通过模拟实例和讲解介绍这个过程。
2、失败前场景说明
日志中记录过程如下:
1、事务A进行之后,结束commit。之后系统进行了一次checkpoint A;
2、Checkpoint之后,进行事务B,结束commit;
3、进行事务C,C事务量较大,其中进行了一定量的Redo Log文件写入。之后系统断电;
1、系统启动过程,进入实例恢复阶段
当实例意外中断的时候,各类型文件,包括控制文件、数据文件和日志文件上,会存在不一致的问题。这种不一致主要体现在SCN值的差异上。
实例在启动的时候,经过三阶段(nomount、mount和open)。在open之前,会进行这种不一致现象的检查,如果出现不一致,要启动SMON进程的恢复流程。
SMON是Oracle实例的一个后台进程,主要负责进行系统监控恢复。进行恢复的依据主要是Redo Log记录。
2、前滚进程
SMON首先找到最后SCN记录的Redo Log File。寻找最后一个打入的Checkpoint。
顺序找到CheckPoint A之后,表示A之前的所有事务都是完全写入到数据文件中,不存在不一致性问题。恢复过程从Checkpoint A开始,Oracle开始依据重做日志Redo Log的系列条目,进行推进。
首先遇到了事务B信息,由于事务B已经commit,所以事务B所有相关的Redo Log条目已经全都写入到Redo Log File中。所以,按照日志继续条目推进,完全可以重演replay,并且应用apply事务B的全部过程。
这样,事务B全部实现,最终将通过DBWn完全写入到数据文件中。所以,实例失败之前提交commit的事务B,完全恢复。
进入事务C的范畴,由于一部分事务C的Redo Log条目已经进入Redo Log File中,所以在进行前滚的时候,一定会replay到这部分的内容。不过,这部分内容中不可能出现commit的标记。
所以,前滚的结果一定是遇到实例突然中断的那个时点。此时replay的结果是,事务C没有提交。这样结束了前滚过程,进入回滚阶段。
3、回滚过程
对事务C,要进行回滚过程,释放所有相关资源。从Undo空间中寻找到旧版本SCN的数据块信息,来进行SGA中Buffer Cache数据块恢复。
4、说说恢复过程的损耗
很多时候,由于我们事务规模较大,当出现实例崩溃的时候,重启所需要的时间很多。有一种经验说法是,事务有多长,前滚和回滚所消耗的时间有多长×2。而且,如果不能完成SMON恢复过程,数据库是不能算作正常的Open的。
SMON的恢复过程是Oracle强制进行的一个过程,即使恢复中发生断电或者其他中断失败事件。Oracle在下一次启动的时候,还是会继续这个过程,只有耐心等待。
通过检查一些内部视图(X$视图),可以观察到恢复进程和速度,但是丝毫不能影响到最终恢复的过程。
这个过程虽然可以保证数据一致性,但是也带来了系统不能启动,影响生产环境的问题。我们可以通过两个方式进行缓解:
首先,我们在设计开发系统时,要保证事务规模的可控性,不要让事务规模在技术层面上过大。避免一旦发生崩溃,大规模强制回滚的发生;
其次,一旦出现了这个强制回滚,要注意对生产环境的影响。可以采用备库standby进行顶替,让主库安静的慢慢恢复;