什么是crash recover?
由于故障导致Instance异常关闭或由于执行了shutdown abort/startup force都会导致数据库实例在重启时执行实例恢复,具体就是SMON来完成这个任务了。实例可以理解为内存级别,不需要人工干预,需要mttr参数控制时间。
为什么要进行crash recover
oracle中存在bufer cache缓冲区,正常运行期间,里面存在很多脏块,如果实例异常,导致脏块未写入磁盘,如果没有什么手段把崩溃后的脏块找回来,肯定会出现数据不一致的情况。当然关系数据库设计之初,这种情况就已经考虑了,通过重做日志,完全可以实现实例crash不丢数据。 总而言之,所有已提交的事务,都是可以恢复的,这样才能保证数据的一致性。
Oracle实例恢复的过程
Oracle scn说明
1、系统检查点scn
每次检查点完成都会记录到控制文件中,由于控制文件是全局的,多库结构下系统只有cdb有全局scn。
SQL> select con_id,checkpoint_change# from v$database;
CON_ID CHECKPOINT_CHANGE#
---------- ------------------
0 4332329
2、数据文件检查点scn(CHECKPOINT_CHANGE#)
每当发生检查点动作时,oracle把每个数据文件SCN保存在控制文件中。
SQL> select CON_ID,CHECKPOINT_CHANGE#,LAST_CHANGE# from v$datafile order by 1;
CON_ID CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
1 4332329
1 4332329
1 4332329
1 4332329
2 2145459 2145459
2 2145459 2145459
2 2145459 2145459
3 4332329
3 4332329
3 4332329
3 4332329
CON_ID CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
4 4332329
4 4332329
4 4332329
5 4332329
5 4332329
5 4332329
8 4332329
8 4332329
8 4332329
20 rows selected.
3、数据文件启动SCN(数据文件头)和终止SCN(LAST_CHANGE#)
每个数据文件头会记录启动SCN,而控制文件会记录每个文件的终止SCN 这两个SCN 来确定文件是否需要恢复。
select CON_ID,CHECKPOINT_CHANGE#,LAST_CHANGE# from v$datafile order by 1;
如果12C以后多库结构,以abort的方式停止pdb和cdb的区别,需要注意。
实例恢复过程
- 如果end scn为空,此时需要实例恢复,smon开始工作进行实例恢复。
这里不讨论media recover的场景,该场景不是实例异常宕机导致的
- 日志前滚,构造实例异常丢失的脏块,确认恢复的起点和终点的显得尤为重要。
检查点队列可以确认数据库恢复的起点,因为检查点队列,是根据数据块第一次脏的时间进行连接,检查点队列最前面的块,就是最早脏的块了,增量检查点会把这个块地址记录到控制文件中,当实例恢复时,就可以确认恢复的起点了(LRBA),**检查点的触发频率,不仅影响数据库读写效率,还会影响数据的崩溃恢复时间,检查点的间隔越大,需要前滚的日志越多,恢复越慢,但是如果间隔越小,刷脏频率增高,IO读写压力会变大,此时增量检查点变的尤为重要**。 恢复的终点比较容易确认,就是on disk RBA,最后一条写到磁盘的redo地址。
-
回滚,有些未提交的事务也会构造出来,但是在undo记录了未提交的事务,只需根据undo记录记性回滚即可。
- RAC架构下实例异常,crash recover该怎么做。
由于RAC是多节点共享访问一份数据,如果一个节点异常关闭,不会等到该节点恢复正常再进行崩溃恢复。因为活着的节点可以完成恢复的过程,同样也是先前滚再回滚,当然在开始之前,必须禁止故障节点访问共享数据,需要对故障节点进行IO Fencing。 这个过程是也是oracle内部机制处理,RAC架构恢复过程和单实例区别在于,故障实例的脏数据恢复过程需要用到PCM-lock来判断,哪些是需要恢复的脏数据,因为正常节点还是会访问共享数据,这个恢复过程更复杂。
总结
无论是单节点还是RAC架构,DBA都无法干预这个过程,但是可以通过一些参数来缩短这个恢复过程,以减少数据库启动的时间。