转载: 深入了解Oracle SCN (1)

时间:2021-01-28 17:33:46

转自:http://space.itpub.net/9765498/viewspace-235733

 

[说明]本来在研究Backup and Recovery,可是在做实验的时候遇到一些问题不是很理解,进而追根求源,想搞清楚,于是必须搞清楚SCN和Recovery之间的关系。于是乎转而研究SCN,这两天看了很多文章,包括Eygle网站上的文章,itpub上biti等大师以前发过或者参与讨论过的帖子,发现思路有模糊到清晰,再由清晰到模糊,越走越深,至今还没有完全搞清楚。决定暂时到此为止,等以后各方面的知识积累多了,再转过来研究一下。本想自己写个总结性的文章,可是发现了一篇文章已经写的很好了,我就懒惰的以逸待劳,copy过来了,在此谢谢前辈们的工作,大家辛苦了~

SCN的概念

SCN是顺序递增的一个数字,在Oracle中用来标识数据库的每一次改动,及其先后顺序。SCN的最大值是0xffff.ffffffff

SCN管理方式

OracleSCN的管理,分为单节点和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 tablespaceoffline normal命令时,就会触发一个checkpoint,将内存中的dirty buffer写入磁盘文件中。Checkpoint完成后,数据文件头会更新checkpoint scnoffline normal scn值。其中数据库文件头的checkpoint scn值可通过查询列x$kccfe.fecps得到。

如果执行SQL>alter tablespaceoffline命令时采用temporaryimmediate选项,而不用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就被设成当前数据库scnredo log也会被重新设置。

Stop SCN

Stop scn记录在数据文件头上。当数据库处在打开状态时,stop scn被设成最大值0xffff.ffffffff。在数据库正常关闭过程中,stop scn被设置成当前系统的最大scn值。在数据库打开过程中,Oracle会比较各文件的stop scncheckpoint scn,如果值不一致,表明数据库先前没有正常关闭,需要做恢复。

High and Low SCN

OracleRedo log会顺序纪录数据库的各个变化。一组redo log文件写满后,会自动切换到下一组redo log文件。则上一组redo loghigh scn就是下一组redo loglow scn

在视图v$log_history中,sequence#代表redo log的序列号,first_change#表示当前redo loglow scn,列next_change#表示当前redo loghigh 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...]