前滚回滚过程应该是这样的:数据库记录了最新的SCN、增量checkpoint的SCN、redo log的最大SCN,通过增量checkpoint的SCN开始应用redo log直到redo log的最大SCN乃至最新的SCN,这样就完成了前滚,在回滚的时候直接读取undo中这个会话最初的scn和前镜像直接回滚,不会一个个数据块去undo,否则如果10G数据写入数据文件但是没有commit那回滚得多久啊
redo、undo用到的原因是:因redo log先于datafile写入持久层,所以实例启动时需要先前滚redo log中修改的数据,如果这些数据没有commit再从undo中回滚回去。
At least every three seconds the checkpoint process records information in the control file about the checkpoint position in the online redo log.
--即使没有发生任何事情,每3秒SCN也必须至少增加1
dbwn进程写入data file的条件系统发出检查点指令(ckpt进程启动后会促使dbwn写data file)。
脏缓冲区个数达到指定阀值。
服务进程搜索一定数目的数据块后,不能找到自由缓冲区。
数据写入计时时间到。
lgwr进程写入redo log的条件在DWBR 进程将脏缓冲区写入数据文件之前
在重做日志记录达到日志缓冲区的三分之一
日志缓冲区记录的日志多于1M
每隔3秒钟
提交事务(执行Commit)
ckpt进程写SCN记录的条件发生日志切换。
关闭实例(SHUTDOWN ABORT 除外)。
手工执行检查点操作。
由初始化参数LOG_CHECKPOINT_INTERVAL 和LOG_CHECKPOINT_TIMEOUT强制发出。
shutdown abort的情况修改过的缓冲区不写入数据文件
不回退未提交的更改
不执行ckpt
undo记录SCN
When a transaction modifies data, the database writes a new SCN to the undo data segment assigned to the transaction
redo记录SCN
LGWR puts a commit record in the redo log buffer and writes it to disk immediately, along with the commit SCN and transaction's redo entries
假如,一个会话A,修改某行的某列数值5为3,但是没有来得及commit,就执行了shutdown abort
这个时候可能有三种情况
1、这个修改写入了data file(写入data file和是否commit没有关系)也写入了redo log(写入了data file则一定会触发先写redo log),数据库startup过程中实例恢复的流程
2、这个修改没有写入了data file,但是写入了redo log(除了commit外,还有4种情况会写入redo log),数据库startup过程中实例恢复的流程
3、这个修改没有写入data file,也没有写入redo log(如果写入redo log的条件都没在会话A期间发生),数据库startup过程中实例恢复的流程
前滚回滚实例恢复都是如下一个流程因为没有ckpt,所以data file和control file没有记录会话A的SCN
如果已经写入了redo log,所以redo log记录了会话A的SCN
如果没有写入了redo log,redo log也至少记录了会话A前3秒(shutdown abort前3秒)的一个SCN
虽然没有ckpt,但是control file仍有一个最新的SCN,v$database.current_scn,此SCN可能还大于redo log的最新SCN
SMON进程发现redo log、data file、control file三者的SCN不一致,则利用redo log进行前滚,同步数据文件、控制文件使这二者和重做日志文件的最新SCN一致,当前滚完成后,发现会话A的数据块的ITL状态是uncommitted,则再使用undo中会话A的前镜像回滚,再一次同步数据文件、控制文件、重做日志文件确保三者都是一致的SCN
shutdown abort后,执行start up会自动更新data file和control file的SCNSQL> select to_char(sysdate,'hh:mm:ss') from dual;
TO_CHAR(
--------
02:03:08
SQL> select CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE#,CURRENT_SCN from v$database;
CHECKPOINT_CHANGE# CONTROLFILE_CHANGE# CURRENT_SCN
------------------ ------------------- -----------
1062765 1062824 1063536
SQL> select distinct CHECKPOINT_CHANGE# from v$datafile_header;
CHECKPOINT_CHANGE#
------------------
1062765
SQL> select distinct CHECKPOINT_CHANGE#,last_change# from v$datafile;
CHECKPOINT_CHANGE# LAST_CHANGE#
------------------ ------------
1062765
SQL> shutdown abort;
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 1272213504 bytes
Fixed Size 1344680 bytes
Variable Size 788532056 bytes
Database Buffers 469762048 bytes
Redo Buffers 12574720 bytes
Database mounted.
Database opened.
SQL> select to_char(sysdate,'hh:mm:ss') from dual;
TO_CHAR(
--------
02:03:50
SQL> select CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE#,CURRENT_SCN from v$database;
CHECKPOINT_CHANGE# CONTROLFILE_CHANGE# CURRENT_SCN
------------------ ------------------- -----------
1083549 1083604 1083812
SQL> select distinct CHECKPOINT_CHANGE# from v$datafile_header;
CHECKPOINT_CHANGE#
------------------
1083549
SQL> select distinct CHECKPOINT_CHANGE#,last_change# from v$datafile;
CHECKPOINT_CHANGE# LAST_CHANGE#
------------------ ------------
1083549
本文标题:数据库startup启动时前滚回滚进行实例恢复的理解
当前链接:
http://dzwzjz.com/article/peipjp.html