author:skate
time:2010/09/07
oracle的resetlogs机制浅析
alter database open resetlogs 这个命令我想大家都很熟悉了,那有没有想过这个resetlogs选项为什么要用?什么时候用?
它的原理机制是什么?他都起哪些作用?
我们都知道数据在启动时候是要做一致性检查的,oracle在open阶段要做两次检查
1. 检查数据文件头的检查点计数(checkpoint cnt)是否和控制文件的检查点计数(checkpoint cnt)一致。目的是确认数据文件
是否来自同一版本,而不是从备份中恢复的。如果这一步检查通过,就进行第二步检查
2. 检查数据文件头的开始scn和控制文件中记录该文件的结束scn是否一致。如果数据文件头的开始scn和控制文件中该文件的结束scn
相等,那说明这个数据文件就不需要恢复,否则就要恢复文件
如果以上两步检查都通过,那就可以正常打开数据库,锁定数据文件,同时将控制文件中每个数据文件的结束scn设置无穷大。
我们在某些条件下打开数据,会提示让用resetlogs选项open数据库,为什么要用resetlogs呢?它是干嘛用的呢?问号一大堆了吧,
下面来具体分析下。
resetlogs的作用
防止陈旧的数据进入数据库(保证数据库的一致性),这也就是为什么在用resetlogs打开数据库,一定要立即对数据库做个全备。
在控制文件,data file header,redo log header里存储”resetlogs data“,当open resetlogs被执行时,可以通过这些内容检查一致性。
什么时候用resetlogs
1. 不完全恢复
2. 用备份的控制文件恢复
3. 新创建的控制文件来恢复
resetlogs的原理机制
resetlogs是如何来保证打开数据库是一致的呢?
1)在open resetlogs时,oracle要对比检查控制文件和数据字典file$,如果一个数据文件在file$中存在,但在控制文件中不存在,
那在控制文件中将创建一个这个文件条目(MISSINGnnn ‘nnn’是十进制的file_id),同时这个文件被标记为离线并需要恢复。如果
实际中这个文件存在的话,可以通过如下sql更改到正确的文件名。
sql> alter database rename file 'MISSINGnnn' to '
然后数据文件被恢复,online。
2)如果一个数据文件存在控制文件中,而不在数据字典file$中,那么直接把控制文件中这个文件的记录条目删除(oracle认为file$文
件是正确的,要以它为准)
3)当用旧的备份控制文件恢复的时候,如果有数据文件不在控制文件中注册(会提示控制文件比较旧的错误),那就不得不重建数据文件
,以使数据文件注册到控制文件中,然后系统会自动利用redo/archivelog恢复这个数据文件。
在保证控制文件和file$文件内容一致之后,oracle还有做如下检查才能open resetlogs
4)数据文件的版本要小于当前数据库的版本(counter)
5)offline的数据文件必须被online或者直接drop
6)所有的数据文件不能设置fuzzy bit,所有的数据文件要有相同的检查点(checkpoint SCN)
到目前为止,open resetlogs的前提条件都已经满足,resetlogs究竟做了哪些工作呢?(重新使用redo log)
1)所有的online logfile 的信息重新被放置在控制文件中。并且还要为有效的thread挑选一个logfile文件作为current logfile
2)log header被更新为log seq#
3)所有的online的数据文件头被新的checkpoint和新的‘resetlogs data’更新,offline的数据文件被标记为需要媒体恢复。
resetlogs data:当前的scn和counter被称作”resetlogs data“
如果oracle数据库一致性检查失败的,那数据库是不允许被open的,即 open resetlogs不成功。但也不是绝对不能open,可以通过隐含参数“_allow_resetlogs_curruption”,
绕过oracle的一致性检查,但这样会引起数据库的不一致(文件可能有不同的scn或有fuzzy
bit设置),如果open后,数据库一定要rebuild (建议ANALYZE TABLE ...VALIDATE STRUCTURE
CASCADE;或者imp/exp )
-------end------
另一篇SCN文章:
http://space.itpub.net/12361284/viewspace-346
Checkpoint和SCN的解析
年初的时候拜读完了eygle写的《深入潜出》这本书,感觉收获很大。正好可以总结一下SCN和checkpoint这两个东东。
Checkpoint
很多人都把checkpoint的概念给复杂化了,其实checkpoint这个数据库概
念引入的真正意义就是用来减少在数据库恢复过程中所花的时间(instance
recovery),那么checkpoint是又谁来做的呢?我们都知道数据库中有个CKPT进程,这个是个可选进程,但是真正执行检查点的任务并不是
有ckpt来完成的,而是ckpt在更新控制文件和数据文件头的有关信息后,通知DBWn进程,产生一个检查点,在产生检查点的时候,DBWn进程会将
buffer cache中的脏数据(当前online redo
log对应的脏数据),写入我们的数据文件当中。那么这个时候如果数据库此时崩溃(比如我们做个shutdown
abort),那么在进行实例恢复的时候就可以不需要当前online redo
log的内容了,会很快就做完。因此ckpt进程只是个辅助进程,他的任务更多的是用来在系统做checkpoint的时候更新控制文件和数据文件头中的
信息。其实在oracle
8i的时候呢,ckpt的任务一般都是由lgwr进程来完成,到了8i以后,随着CKPT进程的引入,lgwr的工作负担就减轻了很多(commit的速
度加快了)
那么如何来产生检查点呢?
有三种方法,可以通过
1.alter system checkpoint
2.alter system switch logfile
3.DBWn进程写出脏块
SCN
在Oracle中理解为一个内部同步时钟,是系统改变号的缩写(system change number),在Oracle数据库中
我们可以通过dbms_flashback包来查询当前系统的改变号:select
dbms_flashback.get_system_change_number from
dual;一般来讲SCN主要是用来标识数据库所做的所有改变,这个SCN的改变是只能前进,不能回退,除非我们打算重建库,数据库中的SCN永远不会归
0,一般来说SCN的前进触发是由commit来进行的,除了这些据我观察每隔3秒种系统也都会刷新一次SCN.
需要注意的是:
1.CKPT
一定是是在checkpoint发生的时候将数据库当前的SCN更新入数据库文件头和控制文件当中,同时DBWn进程将buffer
cache中的脏数据块(dirty block)写到数据文件当中(这个脏数据也一定是当前online redo log保护的那一部分)。
2.同时CKPT进程还会在控制文件当中记录(redo block address)RBA,这个地址用来标志恢复的时候需要从日志中的那个位置开始。
在Oracle数据库中和checkpoint相关的SCN总共有4个
1.System checkpoint SCN (存在于控制文件)
在系统执行checkpoint后,Oracle会更新当前控制文件中的System checkpoint SCN。
我们可以通过
select checkpoint_change# from v$database:
来查看
2.Datafile checkpoint SCN (存在于控制文件)
由
于控制文件中记录了Oracle中各个数据库文件的位置和信息,其中当然也包括了Datafile checkpoint
SCN,因此在执行checkpoint的时候,Oracle还会去更新控制文件中所记录的各个数据文件的datafile checkpoint
SCN.
我们可以通过
select checkpoint_change# from v$datafile;
来查看
3.Start SCN (存在于各个数据文件头)
在执行checkpoint时,Oracle会更新存放在各个实际的数据文件头的Start SCN(注意绝对不会是控制文件中),这个SCN存在的目的是用于检查数据库启动过程中是否需要做media recovery(介质恢复)
我们可以通过
select checkpoint_change# from v$datafile_header;
4.End SCN(存在于控制文件)
最
后一类SCN,End SCN他也是记录在控制文件当中,每一个所记录的数据文件头都有一个对应的End SCN,这个End
SCN一定是存在于控制文件当中。这个SCN存在的绝对意义主要是用来去验证数据库启动过程中是否需要做instance
recovery。我们可以通过
select name,last_change# from v$datafile
那么其实在数据库正常运行的情况下,对于read/write的online 数据文件这个SCN号为#FFFFFF(NULL).
下面来聊一聊SCN号于数据库的启动
1.
在数据库的启动过程中,当System Checkpoint SCN=Datafile Checkpoint SCN=Start
SCN的时候,Oracle数据库是可以正常启动的,而不需要做任何的media recovery。而如果三者当中有一个不同的话,则需要做media
recovery
2.那什么时候需要做instance
recovery呢?其实在正常open数据库的时候,oracle会将记录在控制文件中的每一个数据文件头的End
SCN都设置为#FFFFFF(NULL),那么如果数据库进行了正常关闭比如(shutdown or shutdown
immediate)这个时候,系统会执行一个检查点,这个检查点会将控制文件中记录的各个数据文件头的End
SCN更新为当前online数据文件的各个数据文件头的Start SCN,也就是End SCN=Start
SCN,如果再次启动数据库的时候发现二者相等,则直接打开数据库,并再次将End
SCN设置为#FFFFFF(NULL),那么如果数据库是异常关闭,那么checkpoint就不会执行,因此再次打开数据库的时候End
SCN<>Start SCN这个时候就需要做实例恢复。
说了那么多更新SCN操作什么的,这个更新操作到底是由谁做的呢?其实刚才已经说过了,就是我们的CKPT进程,他不仅仅会更新SCN,而且还会通知DBWn做他的事情。
再说一下System Checkpoint SCN和Datafile Checkpoint SCN,这两个SCN都是记录在控制文件当中的。但是这两个SCN有什么作用呢?
logzgh有段论述,我自己的想了一下,还是学习一下他的结论:
1.对只读表空间,其数据文件的Datafile Checkpoint SCN、Start SCN和END SCN号均相同。这三个SCN在表空间处于只读期间都将被冻结。
2.
如果控制文件不是当前的控制文件(其实就是说,想比当前redo log的SCN来讲,控制文件已经过时了),则System checkpoint
SCN会小于Start SCN(Start
SCN是来自实际的数据文件头,有比较依据)。记录这些SCN号,可以区分控制文件是否是当前的控制文件。当有一个Start
SCN(从当前各个在线数据文件中获得)号超过了System Checkpoit
SCN号时,则说明控制文件不是当前的控制文件,因此在做recovery时需要采用using backup
controlfile。这是为什么需要记录SystemCheckpoint SCN的原因之一。
当我们重建控制文件的时候,重建方式分两种(resetlogs 和 noresetlogs)
1.
使用resetlogs选项时,System Checkpoint SCN为被归为0,而其中记录的各个数据文件的Datafile
Checkpoint SCN则来自于Start
SCN(也就是说可能会从冷备份的数据文件的数据文件头中获取)。根据上述的描述,此时需要采用using backup
controlfile做recovery. 因此情况是 System Checkpoint SCN=0 < Start SCN =
Datafile Checkpoint SCN
2.使用noresetlogs选项时,有一个前提就是:一定要有online
redo log的存在。否则就要使用resetlogs选项。这个时候控制文件重建好时,其system checkpoint
SCN=Datafile Checkpoint SCN=Lastest Checkpoint SCN in online redo
log,我们可以看到Datafile Checkpoint SCN并没有从Start
SCN中读取。而是读取了最新的日志文件中的SCN作为自己的数据。此时重建的控制文件在恢复中的作用跟最新
的控制文件类似,System Checkpoint SCN(已经读取最新的redo log的checkpoint
SCN信息)可能会>Start SCN (因为数据文件可能会从冷备份中恢复),恢复时就不需要加using backup
controlfile子句了
关于backup controlfile的补充:backup
controlfile只有备份时刻的archive log信息,并没有DB crash时刻的archive
log信息,所以并不会自动应用online redo log,而是提示找不到序号为Lastest Archive log sequence + 1
的archive log,尽管你可以手动指定online redo log来实现完全恢复,但因为一旦使用了using backup
controlfile子句,Oracle就视为不完全恢复,必须open resetlogs!
实际上,假如你有旧的控制文件又不想resetlogs,那很简单,使用旧的控制文件mount然后 backup to trace
,然后手工创建控制文件,使用 reuse database ... noresetlogs .这样就可以 recover database
自动恢复并open database 而不用 resetlogs 了
**********************************************
通过试验说明checkpoint cnt 和checkpoint scn的关系
1.在不同条件下转储控制文件
|
Session altered. SQL> alter tablespace system begin backup; Tablespace altered. SQL> alter session set events 'immediate trace name CONTROLF level 10'; Session altered. SQL> alter system checkpoint; System altered. SQL> alter session set events 'immediate trace name CONTROLF level 10' Session altered. SQL> alter tablespace system end backup; Tablespace altered. SQL> alter session set events 'immediate trace name CONTROLF level 10'; Session altered.
|
notes:
alter session set events 'immediate trace name CONTROLF level 10';
用于转储控制文件.
2.获得以下跟踪文件信息(仅研究system表空间记录,请注意红色部分):
a.正常情况下转储控制文件
|
***************************************************************************
|
b.执行Begin backup以后的
我们注意到Checkpoint cnt增加了1,此处触发了一次表空间检查点.
|
***************************************************************************
|
c.执行手工检查点
我们注意到,此时Checkpoint cnt增加,但是scn不再改变
|
***************************************************************************
|
d.End backup后的情况
此时数据文件头的冻结被取消,scn开始变化
|
***************************************************************************
|
Checkpoint cnt用于保证在正常操作中使用的数据文件是当前版本
在恢复时防止恢复数据文件的错误版本.Checkpoint cnt是一直递增的,即使表空间处于热备份模式.
由于表空间的创建时间不尽相同,所以不同表空间/数据文件的Checkpoint cnt通常是不同的.
我们知道:
在数据库open的过程中,Oracle要进行两次检查.
第一次检查数据文件头中的Checkpoint cnt是否与对应控制文件中的Checkpoint cnt一致.
如果相等,进行第二次检查.
第二次检查数据文件头的开始SCN和对应控制文件中的结束SCN是否一致
如果结束SCN等于开始SCN,则不需要对那个文件进行恢复.
对每个数据文件都完成检查后,打开数据库.同时将每个数据文件的结束SCN设置为无穷大.