oracle scn研究

深入了解Oracle SCN (1)

--------------------------------------------------------------------------------


[说明]本来在研究Backup and Recovery,可是在做实验的时候遇到一些问题不是很理解,进而追根求源,想搞清楚,于是必须搞清楚SCN和Recovery之间的关系。于是乎转而研究SCN,这两天看了很多文章,包括Eygle网站上的文章,itpub上biti等大师以前发过或者参与讨论过的帖子,发现思路有模糊到清晰,再由清晰到模糊,越走越深,至今还没有完全搞清楚。决定暂时到此为止,等以后各方面的知识积累多了,再转过来研究一下。本想自己写个总结性的文章,可是发现了一篇文章已经写的很好了,我就懒惰的以逸待劳,copy过来了,在此谢谢前辈们的工作,大家辛苦了~
SCN的概念
SCN是顺序递增的一个数字,在Oracle中用来标识数据库的每一次改动,及其先后顺序。SCN的最大值是0xffff.ffffffff。
SCN的管理方式
Oracle对SCN的管理,分为单节点和RAC两种方式。
单节点的instance中
单节点的instance中,SCN值存在SGA区,由system commit number latch保护。任何进程要得到当前的SCN值,都要先得到这个latch。
RAC/OPS环境中
Oracle通过排队机制(Enqueue)实现SCN在各并行节点之间的顺序增长。具体有两种方法:
Lamport算法:又称面包房算法,先来先服务算法。跟很多银行采用的排队机制一样。客户到了银行,先领取一个服务号。一旦某个窗口出现空闲,拥有最小服务号的客户就可以去空闲窗口办理业务。
Commit广播算法:一有commit完成,最新的SCN就广播到所有节点中。
上述两种算法可以通过调整初始化参数max_commit_propagation_delay来切换。在多数系统(除了Compaq Tur64 Unix)中,该参数的默认值都是700厘秒(centisecond),采用Lamport算法。如果该值小于100厘秒,Oracle就采用广播算法,并且记录在alert.log文件中。
几种重要的SCN
Commit SCN
当用户提交commit命令后,系统将当前scn赋给该transaction。这些信息都反映在redo buffer中,并马上更新到redo log文件里。
Offline SCN
除了System tablespace以外的任何表空间,当我们执行SQL>alter tablespace…offline normal命令时,就会触发一个checkpoint,将内存中的dirty buffer写入磁盘文件中。Checkpoint完成后,数据文件头会更新checkpoint scn和offline normal scn值。其中数据库文件头的checkpoint scn值可通过查询列x$kccfe.fecps得到。
如果执行SQL>alter tablespace…offline命令时采用temporary或immediate选项,而不用normal选项时,offline normal scn会被设成0。这样当数据库重启后通过resetlog方式打开时,该表空间就无法再改回在线状态。
Checkpoint SCN
当数据库内存的脏数据块(dirty blocks)写到各数据文件中时,就发生一次checkpoint。数据库的当前checkpoint scn值存在x$kccdi.discn中。Checkpoint scn在数据库恢复中起着至关重要的作用。无论你用何种办法恢复数据库,只有当各个数据库文件的checkpoint scn都相同时,数据库才能打开。
虽然参数“_allow_resetlogs_corruption”可以在checkpoint scn不一致时强制打开数据库,但是这样的数据库在open后必须马上作全库的export,然后重建数据库并import数据。
Resetlog SCN
数据库不完全恢复时,在指定时间点后的scn都无法再应用到数据库中。Resetlog时的scn就被设成当前数据库scn,redo log也会被重新设置。
Stop SCN
Stop scn记录在数据文件头上。当数据库处在打开状态时,stop scn被设成最大值0xffff.ffffffff。在数据库正常关闭过程中,stop scn被设置成当前系统的最大scn值。在数据库打开过程中,Oracle会比较各文件的stop scn和checkpoint scn,如果值不一致,表明数据库先前没有正常关闭,需要做恢复。
High and Low SCN
Oracle的Redo log会顺序纪录数据库的各个变化。一组redo log文件写满后,会自动切换到下一组redo log文件。则上一组redo log的high scn就是下一组redo log的low scn。
在视图v$log_history中,sequence#代表redo log的序列号,first_change#表示当前redo log的low scn,列next_change#表示当前redo log的high scn。
SQL> col recid format 9999
SQL> col requence# format 9999
SQL> col first_change# format 9,999,999,999,999
SQL> col next_change# format 9,999,999,999,999
SQL> select recid,sequence#,first_change#,next_change# from v$log_history where rownum<6;
RECID SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
----- ---------- ------------------ ------------------
484 484 1,928,645,840,091 1,928,645,840,436
485 485 1,928,645,840,436 1,928,645,840,636
486 486 1,928,645,840,636 1,928,778,045,209
487 487 1,928,778,045,209 1,929,255,480,725
488 488 1,929,255,480,725 1,930,752,214,033
 
SCN号与oracle数据库恢复的关系
SCN号与oracle数据库恢复过程有着密切的关系,只有很好地理解了这层关系,才能深刻地理解恢复的原理,从而才能很好地解决这方面的问题。
SCN与CHECKPOINT
CKPT进程在checkpoint发生时,将当时的SCN号写入数据文件头和控制文件,同时通知DBWR进程将数据块写到数据文件。
CKPT进程也会在控制文件中记录RBA(redo byte address),以标志Recovery需要从日志中哪个地方开始。与checkpoint相关的SCN号有四个,其中三个存在控制文件中,一个存放在数据文件头中。
这四个分别是:
1.System Checkpoint SCN
当checkpoint完成后,ORACLE将System Checkpoint SCN号存放在控制文件中。我们可以通过下面SQL语句查询:
select checkpoint_change# from v$database;
2.Datafile Checkpoint SCN
当checkpoint完成后,ORACLE将Datafile Checkpoint SCN号存放在控制文件中。我们可以通过下面SQL语句查询所有数据文件的Datafile Checkpoinnt SCN号。
select name,checkpoint_change# from v$datafile;
3.Start SCN号
ORACLE将Start SCN号存放在数据文件头中。
这个SCN用于检查数据库启动过程是否需要做Media Recovery.
我们可以通过以下SQL语句查询:
select name,checkpoint_change# from v$datafile_header;
4.End SCN (Stop SCN)号
ORACLE将End SCN号存放在控制文件中。
这个SCN号用于检查数据库启动过程是否需要做Instance Recovery.
我们可以通过以下SQL语句查询:
select name,last_change# from v$datafile;
在数据库正常运行的情况下,对可读写的,online的数据文件,该SCN号为NULL.
我们作个小的试验,内容如下:
在执行检查点进程之前SCN号如下:
System Checkpoint SCN 4609061
--select checkpoint_change# from v$database;
Datafile Checkpoint SCN 4609061
--select name,checkpoint_change# from v$datafile;
Start SCN 4609061
--select name,checkpoint_change# from v$datafile_header;
End SCN空
--select name,last_change# from v$datafile;
执行alter system checkpoint。后的SCN号如下:
System Checkpoint SCN 4609630
--select checkpoint_change# from v$database;
Datafile Checkpoint SCN 4609630
--select name,checkpoint_change# from v$datafile;
Start SCN 4609630
--select name,checkpoint_change# from v$datafile_header;
End SCN null
--select name,last_change# from v$datafile;
SCN不连续原因可能如下:
1.当发生日志组切换的时候
2.当符合LOG_CHECKPOINT_TIMEOUT,LOG_CHECKPOINT_INTERVAL,fast_start_io_target,fast_start_mttr_target参数设置的时候
3.当运行ALTER SYSTEM SWITCH LOGFILE的时候
4.当运行ALTER SYSTEM CHECKPOINT的时候
5.当运行alter tablespace XXX begin backup,end backup的时候
6.当运行alter tablespace ,datafile offline的时候;
SCN号与数据库启动
在数据库启动过程中,当System Checkpoint SCN、Datafile Checkpoint SCN和Start SCN号都相同时,数据库可以正常启动,不需要做media recovery.三者当中有一个不同时,则需要做media recovery。如果在启动的过程中,End SCN号为NULL,则需要做instance recovery。ORACLE在启动过程中首先检查是否需要media recovery,然后再检查是否需要instance recovery。
SCN号与数据库关闭
如果数据库的正常关闭的话,将会触发一个checkpoint,同时将数据文件的END SCN号设置为相应数据文件的Start SCN号。
当数据库启动时,发现它们是一致的,则不需要做instance recovery。在数据库正常启动后,ORACLE会将END SCN号设置为NULL。如果数据库异常关闭的话,则END SCN号将为NULL.
为什么需要System checkpoint SCN号与Datafile Checkpoint SCN号
为什么ORACLE会在控制文件中记录System checkpoint SCN号的同时,还需要为每个数据文件记录
Datafile Checkpoint SCN号?
原因有二:
1.对只读表空间,其数据文件的Datafile Checkpoint SCN、Start SCN和END SCN号均相同。
这三个SCN在表空间处于只读期间都将被冻结。
2.如果控制文件不是当前的控制文件,则System checkpoint会小于Start SCN或END SCN号。记录这些SCN号,可以区分控制文件是否是当前的控制文件。
Recovery database using backup controlfile
当有一个Start SCN号超过了System Checkpoit SCN号时,则说明控制文件不是当前的控制文件,因此在做recovery时需要采用using backup controlfile。这是为什么需要记录SystemCheckpoint SCN的原因之一。
这里需要一提的是,当重建控制文件的时候,System Checkpoint SCN为0,Datafile Checkpoint SCN的数据来自于Start SCN。根据上述的描述,此时需要采用using backup controlfile做recovery。
重建控制文件,重建方式分两种(resetlogs和noresetlogs)(此段内容来自:http://space.51CTO提醒您,请勿滥发广告!/12361284/viewspace-346)
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了(记住:必须有所有的online redo logs才可以这样!)。
备份的控制文件不能自动进行完全恢复
可以手工apply日志进行完全恢复
 
重新创建的可以自动进行完全恢复(By biti)
示例
例子背景:
oracle 8i
windows
采用rman做热备,在备份期间,做不少事务,同时做alter system checkpoint.
RMAN> run {
2> allocate channel c1 type disk;
3> backup database filesperset 3 format 'e:/full_%p_%t.bak';
4> }
(这里需要一提的是,在这个备份角本里面我们加了filesperset 3。这样将整个数据库分成两个备份集。这样还原出来的数据文件其checkpoint_change#将不一样。否则由于数据库数据文件不多,都将包含在一个备份集中,这样即使在备份中做insert操作和alter system checkpoint也不会产生不同的checkpoint_change#。因为rman备份是将一个备份集中的文件同时备份的。
而checkpoint_change#是存放在数据文件头部的,这样备份这些数据文件的头部的时间将是很快的。)
然后
RMAN> run{
2> allocate channel c1 type disk;
3> restore database;
4> }

SQL> select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
------------------
2156662354
SQL> select file#,checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 2156662355
2 2156662354
3 2156662322
4 2156662354
5 2156662354
6 2156662354
SQL> select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ -------------
1 2156662355
2 2156662349
3 2156662322
4 2156662342
5 2156662349
6 2156662342
从这里可以看出,显然是需要做media recovery的。正常情况下,还需要做instance recovery.当然由于没有在线日志,所以只能做resetlogs。
1.有归档日志存
若有归档日志在,则只需要做一个recover database until cancel;
然后即可alter database open resetlogs;

SQL> recover database until cancel (using backup controlfile);
ORA-00279: change 2156621770 generated at 10/07/2005 14:30:06 needed for thread 1
ORA-00289: suggestion : D:ORACLE8IRDBMSARC00738.001
ORA-00280: change 2156621770 for thread 1 is in sequence #738

Specify log: {=suggested | filename | AUTO | CANCEL}
auto
ORA-00279: change 2156621779 generated at 10/07/2005 14:30:51 needed for thread
1
ORA-00289: suggestion : D:ORACLE8IRDBMSARC00739.001
ORA-00280: change 2156621779 for thread 1 is in sequence #739
ORA-00278: log file 'D:ORACLE8IRDBMSARC00738.001' no longer needed for this recovery

ORA-00308: cannot open archived log 'D:ORACLE8IRDBMSARC00739.001'
ORA-27041: unable to open file
OSD-04002: unable to open file
O/S-Error: (OS 2) 系统找不到指定的文件。

SQL> alter database open resetlogs;
Database altered.

2.无归档日志
如果没有归档日志,由于restore出来是没有在线日志的。
如果v$datafile_header中checkpoint_change#是相同的,此时由于控制文件中checkpoint_change#比数据文件头中要高,所以数据库还是需要做media recovery。
此时重建控制文件还是一样的,因为重建控制文件后,在控制文件中checkpoint_change#为0,与文件头的checkpoint_change#还是不一样,还需要media recovery.且由于控制文件中checkpoint_change#比文件头中要高,所以做recover时还需要加上using backup controlfile.
注意,这时由于没有在线日志,所以重建控制文件需要将noresetlogs改成RESETLOGS才可以创建成功,否则会报以下错误:
ORA-01565: error in identifying file 'D:ORACLE8IORADATAORA8IREDO01.LOG'
ORA-27041: unable to open file
如:
CREATE CONTROLFILE REUSE DATABASE "ORA8I" RESETLOGS ARCHIVELOG
MAXLOGFILES 32
MAXLOGMEMBERS 2
MAXDATAFILES 254
MAXINSTANCES 1
MAXLOGHISTORY 226
LOGFILE
GROUP 1 'D:ORACLE8IORADATAORA8IREDO01.LOG' SIZE 1M,
GROUP 2 'D:ORACLE8IORADATAORA8IREDO02.LOG' SIZE 1M,
GROUP 3 'D:ORACLE8IORADATAORA8IREDO03.LOG' SIZE 1M
DATAFILE
'D:ORACLE8IORADATAORA8ISYSTEM01.DBF',
'D:ORACLE8IORADATAORA8IRBS01.DBF',
'D:ORACLE8IORADATAORA8IUSERS01.DBF',
'D:ORACLE8IORADATAORA8ITEMP01.DBF',
'D:ORACLE8IORADATAORA8ITOOLS01.DBF',
'D:ORACLE8IORADATAORA8IINDX01.DBF'
CHARACTER SET ZHS16GBK
;
此时scn号信息如下:
SQL> select CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE# from v$database;
CHECKPOINT_CHANGE# CONTROLFILE_CHANGE#
------------------ -------------------
0 0

此时由于没有归档日志和在线日志,无法做recovery。
SQL> recover database using backup controlfile until cancel;
ORA-00279: change 2156662342 generated at 10/07/2005 17:06:27 needed for thread 1
ORA-00289: suggestion : D:ORACLE8IRDBMSARC00749.001
ORA-00280: change 2156662342 for thread 1 is in sequence #749
Specify log: {=suggested | filename | AUTO | CANCEL}
cancel
ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below
ORA-01152: file 1 was not restored from a sufficiently old backup
ORA-01110: data file 1: 'D:ORACLE8IORADATAORA8ISYSTEM01.DBF'
ORA-01112: media recovery not started
所以也就无法做alter database open Resetlogs了。
此时可以加上_allow_resetlogs_corruption隐含参数,然后就可以alter database open resetlogs将数据库打开了。

当然如果v$datafile_header中checkpoint_change#是不相同的,那么此时就没有什么常归有效的办法能将数据库打开了。
如果相差不多,加上隐含参数_allow_resetlogs_corruption,然后alter database open resetlogs还是有可能可以打开的。这个参数oracle是不建议加的,且加上这个参数也只是有可能可以打开。这个参数是以最oldest的scn将数据库打开,所以最好system数据文件的scn号是最oldest的,否则容易产生大量的600号错误。
[The End]

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值