ORACLE SCN 深入解析

最近在学习备份恢复,发现SCN号在深入理解恢复还是很重要的,于是就整理了一下网上关于SCN的各种讲解和实验。

在理解SCN之前,我们先看下oracle事务中的数据变化是如何写入数据文件的:

1、事务开始;

2、在buffer cache中找到需要的数据块,如果没有找到,则从数据文件中载入buffer cache中;

3、事务修改buffer cache的数据块,该数据被标识为“脏数据”,并被写入log buffer中;

4、事务提交,LGWR进程将log buffer中的“脏数据”写入redo log file中;

5、当发生checkpoint,CKPT进程更新所有数据文件的文件头中的信息,DBWn进程则负责将Buffer Cache中的脏数据写入到数据文件中。


1.SCN概念(The  System Change  Number)
SCN可以理解为一个逻辑时钟来记录数据库事件,也就是一个顺序递增的数字。
SCN的最大值是0xffff.ffffffff。

2.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文件中。

3.SCN号是怎么产生的呢
实际上,这个数字是由当时的timestamp转换过来的。每当需要产生一个最新的SCN到redo记录时,系统获取当时的timestamp,将其转换为数字作为SCN。
我们可以通过函数SCN_TO_TIMESTAMP(10g以后)将其转换回timestamp
SQL> select  dbms_flashback.get_system_change_number scn, scn_to_timestamp(dbms_flashback.get_system_change_number)  time   from  dual;

       SCN  TIME
----------  --------------------------------
   3056178  16-MAR-12 03.32.58.000000000 PM

也可以用函数timestamp_to_scn将一个timestamp转换为SCN:
SQL> select  timestamp_to_scn(sysdate)  from  dual;

TIMESTAMP_TO_SCN(SYSDATE)
-------------------------
                  3056200

4.几种重要的SCN

Commit SCN
在一个事务提交后(上述第四个步骤),会在redo log中存在一条redo记录,同时,系统为其提供一个最新的SCN(通过函数dbms_flashback.get_system_change_number可以知道当前的最新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


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方式打开时,该表空间就无法再改回在线状态。(resetlogs里面还是有很多东西要学习和理解的)

Checkpoint SCN
与checkpoint相关的SCN号有四个,其中三个存在控制文件中,一个存放在数据文件头中,下面在SCN于数据库恢复的关系是 会有详细的讲解)

当数据库内存的脏数据块(dirty blocks)写到各数据文件中时,就发生一次checkpoint。数据库的当前checkpoint scn值存在x$kccdi.discn中。Checkpoint scn在数据库恢复中起着至关重要的作用。无论你用何种办法恢复数据库,只有当各个数据库文件的checkpoint scn都相同时,数据库才能打开。

虽然参数“_allow_resetlogs_corruption”可以在checkpoint scn不一致时强制打开数据库,但是这样的数据库在open后必须马上作全库的export,然后重建数据库并import数据。


5.SCN号与oracle数据库恢复的关系

SCN号与oracle数据库恢复过程有着密切的关系,只有很好地理解了这层关系,才能深刻地理解恢复的原理,从而才能很好地解决这方面的问题。

SCN与CHECKPOINT

CKPT进程在checkpoint发生时,将当时的SCN号写入所有非只读数据文件头无论redo log中的数据是否影响到该数据文件)同时将控制文件中的System Checkpoint SCN(通过视图v$database的字段checkpoint_change#可以查询)、每个数据文件对应的Datafile Checkpoint(通过视图v$datafile的字段checkpoint_change#可以查询),同时通知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:
SQL> select checkpoint_change#  from  v$database;


CHECKPOINT_CHANGE#
------------------
           3053495

Datafile Checkpoint   scn:

NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf                 3053495

/opt/app/oracle/oradata/orcl/undotbs01.dbf               3053495

/opt/app/oracle/oradata/orcl/sysaux01.dbf                 3053495
          
/opt/app/oracle/oradata/orcl/users01.dbf                   3053495
          
/home/oracle/dpump/part1.dbf                                    3031971

注:我们看到各个数据文件头中记录的start scn号都是相同的(但是/home/oracle/dpump/part1.dbf 却跟其他不一样,原因是这里part.dbf  所在的表空间是只读的,数据文件的Start SCN和控制文件中Datafile Checkpoint SCN都不会被更新。)
          
Start SCN:
SQL> select name,checkpoint_change# from v$datafile_header;
NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf                 3053495

/opt/app/oracle/oradata/orcl/undotbs01.dbf               3053495

/opt/app/oracle/oradata/orcl/sysaux01.dbf                 3053495
          
/opt/app/oracle/oradata/orcl/users01.dbf                   3053495
          
/home/oracle/dpump/part1.dbf                                    3031971

End SCN:
SQL>select name,last_change# from v$datafile;
NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf               

/opt/app/oracle/oradata/orcl/undotbs01.dbf              

/opt/app/oracle/oradata/orcl/sysaux01.dbf                
          
/opt/app/oracle/oradata/orcl/users01.dbf                   
          
/home/oracle/dpump/part1.dbf                                    3031971

注:在数据库正常运行的情况下,对可读写的,online的数据文件,该SCN号为NULL. 对于只读文件,stop scn号3031971 与 start scn号3031971,Datafile Checkpoint   scn3031971  是相同的,


执行alter system checkpoint。后的SCN号如下:
System Checkpoint SCN:
SQL> select checkpoint_change#  from  v$database;
CHECKPOINT_CHANGE#
------------------
           3055942
Datafile Checkpoint SCN :
SQL>select  name ,checkpoint_change#  from  v$datafile;
NAME                                                                         CHECKPOINT_CHANGE#
/opt/app/oracle/oradata/orcl/system01.dbf                    3055942
        
/opt/app/oracle/oradata/orcl/undotbs01.dbf                   3055942
       
/opt/app/oracle/oradata/orcl/sysaux01.dbf                    3055942
 
/opt/app/oracle/oradata/orcl/users01.dbf                      3055942
            
/home/oracle/dpump/part1.dbf                                       3031971
          
Start SCN:
SQL>select name,checkpoint_change# from v$datafile_header;
NAME                                                                         CHECKPOINT_CHANGE#
/opt/app/oracle/oradata/orcl/system01.dbf                    3055942
        
/opt/app/oracle/oradata/orcl/undotbs01.dbf                   3055942
       
/opt/app/oracle/oradata/orcl/sysaux01.dbf                    3055942
 
/opt/app/oracle/oradata/orcl/users01.dbf                      3055942
            
/home/oracle/dpump/part1.dbf                                       3031971

End SCN :
SQL>select name,last_change# from v$datafile;
NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf               

/opt/app/oracle/oradata/orcl/undotbs01.dbf              

/opt/app/oracle/oradata/orcl/sysaux01.dbf                
          
/opt/app/oracle/oradata/orcl/users01.dbf                   
          
/home/oracle/dpump/part1.dbf                                    3031971
注:对只读表空间,其数据文件的Datafile Checkpoint SCN、Start SCN和END SCN号均相同。
这三个SCN在表空间处于只读期间都将被冻结。

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的时候;

6.SCN号与数据库启动
第一步:在数据库启动过程中,检查System Checkpoint SCN、Datafile Checkpoint SCN和Start SCN号都相同时,如果相同数据库可以正常启动,不需要做media recovery.三者当中有一个不同时,则需要做media recovery。
第二步:在不需要做media recovery情况下,若End SCN号为NULL,则需要做instance recovery。

ORACLE在启动过程中首先检查是否需要media recovery,然后再检查是否需要instance recovery。

7.SCN号与数据库关闭

数据库在正常关闭(shutdown immediate/normal)时,会先做一次checkpoint,将log file中的数据写入数据文件中,将控制文件、数据文件中的SCN(包括控制文件中的Stop SCN)都更新为最新的SCN。数据库异常/意外关闭不会或者只更新部分Stop SCN。


在理解和学习resetlog的时候,SCN还是会用到的!!


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值