[说明]本来在研究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
[To be continued...]