SCN、Checkpoint、实例恢复介质恢复理解

如果LGWR的下一个日志是ACTIVE,那么LWGR会挂起,警告日志会报告"Checkpoint not complete",oracle会发起alter system checkpoint的操作
状态为ACTIVE的日志也可能已经是归档日志了,ARCn进程会自动将非CURRENT的在线日志归档

V$LOG.STATUS反应的是完全检查点的进度,因为alter system switch logfile后还是会发现原来为ACTIVE的日志还是ACTIVE状态,但是alter system checkpoint后就一定会把ACTIVE变成INACTIVE(完全检查点写入控制文件和数据文件头部,增量检查点只写入控制文件)

V$LOG.STATUS=ACTIVE
Log is active but is not the current log. It is needed for crash recovery. It may be in use for block recovery. It may or may not be archived.
代表最近一次的完全检查点SCN小于该日志中最后一条重做记录的SCN,说明完全检查点还没有越过这个在线日志
V$LOG.STATUS=INACTIVE
Log is no longer needed for instance recovery. It may be in use for media recovery. It may or may not be archived.
代表最近一次的完全检查点SCN大于该日志中最后一条重做记录的SCN,说明完全检查点已经越过这个在线日志

v$log.FIRST_CHANGE#:等于上一个online redo的v$log.NEXT_CHANGE#或上一个archive redo log的$archived_log.NEXT_CHANGE#,等于下一个archive redo log的v$archived_log.FIRST_CHANGE#
v$log.NEXT_CHANGE#:Highest change number (SCN) in the log. When STATUS=CURRENT, NEXT_CHANGE# is set to the highest possible SCN, 281474976710655

V$DATABASE displays information about the database from the control file.
V$DATABASE.CHECKPOINT_CHANGE#:Last SCN checkpointed
V$DATABASE.CONTROLFILE_CHANGE#:Last SCN in backup control file; null if the control file is not a backup
V$DATABASE.CURRENT_SCN:Current SCN; null if the database is not currently open. For a standby database, it is the checkpoint SCN of the mounted physical standby database during media recovery and is always less than the last applied SCN tracked in V$RECOVERY_PROGRESS.

V$DATAFILEdisplays datafile information from the control file.
V$DATAFILE.CHECKPOINT_CHANGE#:SCN at last checkpoint

V$DATAFILE_HEADERdisplays datafile information from the datafile headers.
V$DATAFILE_HEADER.CHECKPOINT_CHANGE#:Datafile checkpoint change#

控制文件中保存的控制文件SCN是指v$database.CONTROLFILE_CHANGE#
控制文件中保存的数据库SCN(也称系统检查点SCN)是指v$database.CHECKPOINT_CHANGE#
控制文件中保存的数据文件SCN是指v$datafile.CHECKPOINT_CHANGE#
控制文件中保存的数据文件结束SCN是指v$datafile.last_change#,open状态下是null,mount下和数据库检查点scn一致
数据文件中保存的数据文件头SCN是指v$datafile_header.CHECKPOINT_CHANGE#,叫start SCN,也叫启动SCN。
redo logfile中保存的SCN:每一个日志文件有一个first scn和一个next scn。归档日志中,下一个日志文件的first SCN等于上一个日志文件的next SCN,在线日志中,first SCN等于最后一个归档日志的next SCN,而next SCN不论是在open还是mount状态下都是无穷大

数据文件SCN会出现不一致现象,因为数据文件的状态会出现online和offline或begin backup

v$datafile.checkpoint_change#是控制文件里记录某个数据文件比如A的SCN值
v$datafile_header.checkpoint_change#是数据文件比如A记录自己的SCN值
默认情况下这两都应该是一样的。关于两个checkpoint_change#值的比较:
如果datafile大于datafile_header,那么就需要recover datafile,说明控制文件里记录的SCN比数据文件记录的要新。产生原因:shutdown abort等。
如果datafile小于datafile_header,任何情况下都不可能发生,控制文件里的scn不可能比数据文件


执行alter system switch logfile时,只有V$DATABASE.CONTROLFILE_CHANGE#变大了,其他V$DATABASE.CHECKPOINT_CHANGE#、V$DATAFILE.CHECKPOINT_CHANGE#、V$DATAFILE_HEADER.CHECKPOINT_CHANGE#都没有变

执行ALTER DATABASE BEGIN BACKUP时,V$DATABASE.CONTROLFILE_CHANGE#、V$DATAFILE.CHECKPOINT_CHANGE#、V$DATAFILE_HEADER.CHECKPOINT_CHANGE#都变大了,只有V$DATABASE.CHECKPOINT_CHANGE#没变

执行alter tablespace users begin backup时,V$DATABASE.CONTROLFILE_CHANGE#、对应的表空间文件V$DATAFILE.CHECKPOINT_CHANGE#、对应的表空间文件V$DATAFILE_HEADER.CHECKPOINT_CHANGE#变大了,$DATABASE.CHECKPOINT_CHANGE#没变,其他表空间文件的V$DATAFILE.CHECKPOINT_CHANGE#、$DATAFILE_HEADER.CHECKPOINT_CHANGE#也没变

执行alter system checkpoint时,则V$DATABASE.CONTROLFILE_CHANGE#、V$DATABASE.CHECKPOINT_CHANGE#、V$DATAFILE.CHECKPOINT_CHANGE#、V$DATAFILE_HEADER.CHECKPOINT_CHANGE#都变大了


查询相应SCN的一些语句
select CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE#,CURRENT_SCN from v$database;
select distinct CHECKPOINT_CHANGE#,last_change# from v$datafile; 
select distinct CHECKPOINT_CHANGE# from v$datafile_header; 
select distinct FIRST_CHANGE#,NEXT_CHANGE#,sequence#,first_time from v$archived_log order by first_time desc;
select SEQUENCE#,STATUS,ARCHIVED,FIRST_CHANGE#,NEXT_CHANGE# from v$log

mount状态下scn不会改变


查询当前SCN的SQL
一般使用如下
select to_char(dbms_flashback.get_system_change_number) scn from dual
mount状态执行上述语句会报错ORA-00904

下面这条查询语句,每执行一次scn就会增加一次
select CURRENT_SCN from v$database;
mount状态下执行上述语句结果是0



COMMIT Statement
The COMMIT statement ends the current transaction, making its changes permanent and visible to other users.
COMMIT不会触发任何的checkpoint,只是触发lgwr把日志缓冲数据写入在线重做日志并把事务对应的数据块的最新scn和是否的提交状态记录在控制文件中,但是不会记录在任何视图中,V$DATABASE.CURRENT_SCN虽然也来自来自控制文件,但是记录当前最新的SCN

database checkpoint
The thread checkpoint that has the lowest SCN. All changes in all enabled redo threads with SCNs before the database checkpoint SCN are guaranteed to have been written to disk.
具有最低SCN的线程检查点。 在数据库检查点SCN之前所有启用的具有SCN的重做线程的所有更改都保证已写入磁盘。

data file checkpoint
A data structure that defines an SCN in the redo thread of a database for a particular data file. Every data file has a checkpoint SCN, which you can view in V$DATAFILE.CHECKPOINT_CHANGE#. All changes with an SCN lower than this SCN are guaranteed to be in the data file.
数据结构,用于定义特定数据文件的数据库重做线程中的SCN。 每个数据文件都有一个检查点SCN,您可以在V$DATAFILE.CHECKPOINT_CHANGE#中查看。 SCN低于此SCN的所有更改都将保证在数据文件中。


Overview of Checkpoints
A checkpoint is a crucial mechanism in consistent database shutdowns, instance recovery, and Oracle Database operation generally. The term checkpoint has the following related meanings:
A data structure that indicates the checkpoint position, which is the SCN in the redo stream where instance recovery must begin
The checkpoint position is determined by the oldest dirty buffer in the database buffer cache. The checkpoint position acts as a pointer to the redo stream and is stored in the control file and in each data file header.
The writing of modified database buffers in the database buffer cache to disk
检查点是一致的数据库关闭,实例恢复和Oracle数据库操作的关键机制。 检查点一词具有以下相关含义:
指示检查点位置的数据结构,该位置是实例恢复必须开始的重做流中的SCN
检查点位置由数据库缓冲区缓存中最旧的脏缓冲区确定。 检查点位置用作指向重做流的指针,存储在控制文件和每个数据文件头中。
将数据库缓冲区中的修改后的数据库缓冲区写入磁盘


When Oracle Database Initiates Checkpoints
The checkpoint process (CKPT) is responsible for writing checkpoints to the data file headers and control file. Checkpoints occur in a variety of situations. For example, Oracle Database uses the following types of checkpoints:
Thread checkpoints
The database writes to disk all buffers modified by redo in a specific thread before a certain target. The set of thread checkpoints on all instances in a database is a database checkpoint. Thread checkpoints occur in the following situations:
Consistent database shutdown
ALTER SYSTEM CHECKPOINT statement
Online redo log switch
ALTER DATABASE BEGIN BACKUP statement
Tablespace and data file checkpoints
The database writes to disk all buffers modified by redo before a specific target. A tablespace checkpoint is a set of data file checkpoints, one for each data file in the tablespace. These checkpoints occur in a variety of situations, including making a tablespace read-only or taking it offline normal, shrinking a data file, or executing ALTER TABLESPACE BEGIN BACKUP.
检查点进程(CKPT)负责将检查点写入数据文件头文件和控制文件。 检查点发生在各种情况。 例如,Oracle数据库使用以下类型的检查点:
线程检查点
数据库通过在某个目标之前的特定线程中重做修改的所有缓冲区写入磁盘。 数据库中所有实例上的一组线程检查点是一个数据库检查点。 线程检查点在以下情况下发生:
一致的数据库关机
ALTER SYSTEM CHECKPOINT语句
在线重做日志切换
ALTER DATABASE BEGIN BACKUP语句
表空间和数据文件检查点
数据库将磁盘上的所有缓冲区写入特定目标之前通过重做修改。 表空间检查点是一组数据文件检查点,一个用于表空间中的每个数据文件。 这些检查点发生在各种情况下,包括使表空间为只读或正常脱机,收缩数据文件或执行ALTER TABLESPACE BEGIN BACKUP。

oracle规定:保证重做记录先于对应的脏数据块写入持久层
所以,令同一个更改产生的重做记录为R、脏数据块为D,那么lgwr没有把R写入在线日志的情况下,oracle是不允许dbwr把D先行写入数据文件的。即便是dbwr首先发出请求,也必须等待lgwr先清空日志缓冲。这样,数据文件中的内容永远没有在线日志的内容更新得快,也就是在数据库打开的情况下,数据文件永远比在线日志“旧”,为了标识数据文件“旧”到什么程度,oracle便引入了检查点。

Oracle通过检查点(Checkpoint)来缩减恢复时间。检查点只是一个数据库事件,它存在的根本意义在于减少恢复时间。

完全检查点步骤
1.在日志缓冲中确定当前的(也是最新的)重做记录,提取其RBA和SCN作为检查点的目标
2.lgwr清空日志缓冲,将重做记录写入在线日志
3.dbwr进程将检查点目标(RBA与SCN)产生的及检查点目标之前产生的脏数据块,按RBA的顺序写入数据文件
4.ckpt进程将检查点目标(RBA与SCN)写入数据文件的头部和控制文件

这样数据文件头部的检查点目标(RBA与SCN)便能提供如下信息
1.读取数据文件头的检查点scn与在线日志重做记录的scn比较,就可以知道该数据文件是否需要恢复
2.如果该数据文件需要恢复,数据文件SCN用来表示从这个SCN开始恢复

完全检查点发生时机
1.shutdown、shutdown normal、shutdown transactional、shutdown immediate命令
2.alter system checkpoint
3.ALTER DATABASE BEGIN BACKUP
4.执行部分表空间维护命令如alter tablespace tablespacename offline|online|begein backup|end backup|read only|read write

--Online redo log switch时只有V$DATABASE.CONTROLFILE_CHANGE#变大
--ALTER DATABASE BEGIN BACKUP时$DATABASE.CHECKPOINT_CHANGE#没变,虽然V$DATABASE.CONTROLFILE_CHANGE#、V$DATAFILE.CHECKPOINT_CHANGE#、V$DATAFILE_HEADER.CHECKPOINT_CHANGE#都变大
--alter tablespace users begin backup时,V$DATABASE.CONTROLFILE_CHANGE#、对应的表空间文件V$DATAFILE.CHECKPOINT_CHANGE#、对应的表空间文件V$DATAFILE_HEADER.CHECKPOINT_CHANGE#变大,$DATABASE.CHECKPOINT_CHANGE#和?其他表空间对应数据文件CHECKPOINT_CHANGE#没变

完全检查点:个人更愿意理解只有V$DATABASE.CHECKPOINT_CHANGE#增加了才算发生了一次完全检查点。虽然完全检查点的定义是只要同时写入数据文件头部和控制文件就认为是完全检查点。不过按个人理解其实上面BEGIN BACKUP这样的操作就不算完全检查点了。





Incremental checkpoints
An incremental checkpoint is a type of thread checkpoint partly intended to avoid writing large numbers of blocks at online redo log switches. DBWn checks at least every three seconds to determine whether it has work to do. When DBWn writes dirty buffers, it advances the checkpoint position, causing CKPT to write the checkpoint position to the control file, but not to the data file headers.
Other types of checkpoints include instance and media recovery checkpoints and checkpoints when schema objects are dropped or truncated.
增量检查点是一种类型的线程检查点,部分是为了避免在线重做日志切换中写入大量块。 DBWn至少每三秒检查一次,以确定是否有工作要做。 当DBWn写入脏缓冲区时,它会提前检查点位置,导致CKPT将检查点位置写入控制文件,而不是数据文件头。
其他类型的检查点在模式对象被删除或截断时包括实例和介质恢复检查点和检查点。

增量检查点
增量检查点会推动dbwr将部分脏数据块写回数据文件,但是检查点SCN只是记录到控制文件即V$DATABASE.CONTROLFILE_CHANGE#,而没有写入数据文件头部。实例恢复操作并不会因此而少索取日志记录。比如:增量检查点SCN到200了,意味着数据文件内数据块的最高的SCN也已经是200了,但是数据文件头部可能还写着检查点SCN是100,如果此时实例崩溃,实例恢复的前滚会从scn为100的重做记录开始,实际上从scn号100~200的重做记录根本不需要前滚。oracle当然了解这一点,所以每次写完脏数据块之后,dbwr会添加一条被称为BWR(block written record,数据块已写)的重做记录,该记录的变更矢量不代表任何变更,只是用来标记哪些数据块已经被写回数据文件了。
因为有BWR这样的记录,oracle在进行自动前滚时实际上采用“两次读取法”读取在线日志,仍然假设数据文件检查点scn为100,增量检查点已经到200了,第一次读取日志中scn号100后的所有重做记录,目的是确定所有的真正的需要恢复的数据块有哪些,BWR记录就像一个过滤器,可以大量减少这样的数据块。第二次读取在线日志时oracle只对真正需要恢复的数据块,即没有被BWR记录点到名的数据块的重做记录感兴趣。结果是oracle会跳过scn从100到200之间的重做记录,也就会使前滚相应变快

增量检查点作用:
1.减少发生完全检查点是dbwr进程的工作负担
2.提高实例恢复的速度

增量检查点发生时机
1.oracle自动控制(当三个参数都不设置或三个参数都设置不当时FAST_START_MTTR_TARGET、LOG_CHECKPOINT_TIMEOUT、LOG_CHECKPOINT_INTERVAL)
2.三个参数取最严厉的那个(FAST_START_MTTR_TARGET、LOG_CHECKPOINT_TIMEOUT、LOG_CHECKPOINT_INTERVAL)
3.lgwr切换在线日志
--alter system flush buffer_cache不会引发增加检查点

因为lgwr切换在线日志产生增量检查点,说明完全检查点(数据文件头部scn)还没有越过active的在线日志,但是增量检查点(控制文件scn)已经越过了active的在线日志可能已经在current的在线日志了,因为recover时使用两次读取法,先读完全检查点再去增量检查点,所有recover的时候还是需要active的在线日志和current的在线日志,也就是说,current在线日志丢失时,如果还有active的在线日志,不能只恢复到active的在线日志,还需要current的日志,因为增量检查点可能已经在current的日志。


增量检查点的三个参数
FAST_START_MTTR_TARGET默认为0,LOG_CHECKPOINT_INTERVAL默认为0,LOG_CHECKPOINT_TIMEOUT默认为1800

FAST_START_MTTR_TARGET enables you to specify the number of seconds the database takes to perform crash recovery of a single instance. When specified,FAST_START_MTTR_TARGET is overridden by LOG_CHECKPOINT_INTERVAL.
当设置了LOG_CHECKPOINT_INTERVAL时,LOG_CHECKPOINT_INTERVAL的设置会覆盖FAST_START_MTTR_TARGET的设置,而不是说11G已经取消了FAST_START_MTTR_TARGET这个参数的功能。

LOG_CHECKPOINT_INTERVALspecifies the frequency of checkpoints in terms of the number of redo log file blocks that can exist between an incremental checkpoint and the last block written to the redo log. This number refers to physical operating system blocks, not database blocks 
这里指的blocks是OS的block,而不是DATABASE的block
Regardless of this value, a checkpoint always occurs when switching from one online redo log file to another. Therefore, if the value exceeds the actual redo log file size,checkpoints occur only when switching logs. Checkpoint frequency is one of the factors that influence the time required for the database to recover from an unexpected failure
当LOG_CHECKPOINT_INTERVAL值大于redo log file size时,增量检查点发生情况就是在线日志切换取代LOG_CHECKPOINT_INTERVAL
Specifying a value of 0 (zero) for LOG_CHECKPOINT_INTERVAL has the same effect as setting the parameter to infinity and causes the parameter to be ignored. Only nonzero values of this parameter are considered meaningful.
当LOG_CHECKPOINT_INTERVAL为0时,LOG_CHECKPOINT_INTERVAL这个参数就不起作用了
Recovery I/O can also be limited by setting the LOG_CHECKPOINT_TIMEOUT parameter or by the size specified for the smallest redo log.
LOG_CHECKPOINT_TIMEOUT和LOG_CHECKPOINT_INTERVAL都生效,但是取两者更严厉的那个


LOG_CHECKPOINT_TIMEOUTspecifies (in seconds) the amount of time that has passed since the incremental checkpoint at the position where the last write to the redo log(sometimes called the tail of the log) occurred. This parameter also signifies that no buffer will remain dirty (in the cache) for more than integer seconds.
Specifying a value of 0 for the timeout disables time-based checkpoints. Hence, setting the value to 0 is not recommended unless FAST_START_MTTR_TARGET is set
不建议设置LOG_CHECKPOINT_TIMEOUT为0,除非你设置了FAST_START_MTTR_TARGET
FAST_START_MTTR_TARGET、LOG_CHECKPOINT_INTERVAL为0时,LOG_CHECKPOINT_TIMEOUT也生效的



实例恢复的2中情况:
1、增量检查点SCN和在线日志中的SCN进行对比,如果大于在线日志的first_change#,说明和在线日志接上了,可以实例恢复
因为logfile switch就会发生一次增量检查点,所以归档日志总是落后实例的增量检查点,状态为ACTIVE的日志也可能已经是归档日志了,所以实例恢复永远是使用current的在线日志
2、在mount情况下,$datafile.last_change#为空则必须要实例恢复,mount下$datafile.last_change#为空的情况有两种
2.1、shutdown abort
2.2、控制是恢复过来的
数据库OPEN状态下v$datafile.last_change#的SCN号始终为NULL,而当数据库正常关闭时,会进行完全检查点,并将检查点SCN号更新到该字段,
所以可以在mount状态通过v$datafile.last_change#的SCN号是否为null来判断是不是需要实例恢复。而崩溃时,Oracle还来不及更新该字段,则该字段仍然为NULL。当SMON进程发现该字段为空时,就知道实例在上次没有正常关闭,于是由SMON进程就开始进行实例恢复了。SMON进程进行实例恢复时,会从控制文件中获得检查点位置。于是,SMON进程到联机日志文件中,找到该检查点位置,然后从该检查点位置开始往下,应用所有的重做条目,从而在buffer cache里又恢复了实例崩溃那个时间点的状态。这个过程叫做前滚,前滚完成后,buffer cache里既有崩溃时已经提交还没有写入数据文件的脏数据块,也还有事务被突然终止,而导致的既没有提交又没有回滚的事务所弄脏的数据块,这类脏数据块分两种,一种是还在buffer cache中,一种是已经被dbwr写入了磁盘文件。前滚一旦完毕,SMON进程立即打开数据库。但是,这时的数据库中还含有那些既没有提交又没有回滚的脏块,这种脏块是不能存在于数据库中的,因为它们并没有被提交,必须被回滚。打开数据库以后,SMON进程会在后台进行回滚。



介质恢复的情况:
各个数据文件头部检查点scn不一致,增加检查点的SCN远远小于在线日志的first_change#,说明和在线日志接不上,需要介质恢复,需要用到归档日志进行recover(更严重的情况是还可能需要restore数据文件并使用归档日志recover)



RAMN经常遇到的1号文件system太新的问题
如下三者都是说file 1太新了,file 1需要更多的恢复
ORA-01194: file 1 needs more recovery to be consistent 
ORA-01113: file 1 needs media recovery 
RMAN-06556: datafile 1 must be restored from backup older than scn 919248820
datafile 1的scn大于919248820,也就是datafile 1太新了,不够旧不够老
比如正常关机后,startup mount状态,
sql直接recover database会报错ORA-00264: no recovery required
rman直接recover database until sequence到前面几个archivelog就会报RMAN-06556

网站标题:SCN、Checkpoint、实例恢复介质恢复理解
链接地址:http://ybzwz.com/article/iiodce.html