浅谈SCN

SCN(system change number)oracle中很重要的一个机制,在数据恢复,data guardstreams复制,rac节点同步等各个功能中起到重要的作用。

 

我们首先看下oracle事务中数据的变化时怎么写入数据文件的:

 

1.事务开始;

2.buffer cache中找到需要的块,如果没有找到的话,则从数据文件中加载入buffer cache

3.事务修改了buffer cache中的数据,该数据被标示为脏数据”dirty data,同时写入log buffer

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

5.当发生checkpointckpt进程更新所有数据文件文件头的信息,DBWN进程负责将buffer cache中的脏数据写入数据文件。

 

经过上面的5个步骤,事务中变化的数据被写入数据文件中,但是如果中间发生了意外情况,如数据库服务器宕机了,我们就不知道哪些数据已经写入数据文件里了。

 

scn机制就是解决上述的问题。scn是一个只增不减的数字。在oracle中有4scn

1、系统检查点scn
当一个检查点动作完成之后,Oracle就把系统检查点的SCN存储到控制文件中。
select checkpoint_change# from v$database
2、数据文件检查点scn
当一个检查点动作完成之后,Oracle就把每个数据文件的scn单独存放在控制文件
中。
select name,checkpoint_change# from v$datafile
3、启动scn
Oracle把这个检查点的scn存储在每个数据文件的文件头中,这个值称为启动scn,
因为它用于在数据库实例启动时,检查是否需要执行数据库恢复。
select name,checkpoint_change# from v$datafile_header
4、终止scn
每个数据文件的终止scn都存储在控制文件中。
select name,last_change# from v$datafile

在正常的数据库操作过程中,所有正处于联机读写模式下的数据文件的终止scn都为null.

其中前面三个scn被存在控制文件中,开始scn被存储在数据文件中。在控制文件中,系统检查点scn是针对整个数据库的,故只存在一个;而数据文件检查点和结束scn是针对每个数据文件的,因而针对每个数据文件,在控制文件中就应该相应的存在一粉数据文件检查点scn和结束scn。在数据库正常运行期间,stop scn是个无穷大的数字或者null

 

SQL> select last_change# from v$datafile;

LAST_CHANGE#
------------

 

 

 

6 rows selected.

 

 

在一个事务提交了之后,会在redo log中存在一条redo记录,同时,系统为其提供一个scn,记录在该记录中。如果该条记录是在redo log被清空时(日志满了或者发生了checkpoint,所有变化日志已经被写入数据文件中),则scn被记录成redo loglow scn。以后再日志被清空之前写入redo log的记录scnnext scn

当日志切换或发生checkpoint时,从low scnnext scn之间的所有redo记录的数据被DBWn写入数据文件,而ckpt进程则将所有的数据文件文件头的start scn,控制文件的system checkpoint scn,每个数据文件对应的datafile checkpoint也更新为next scn。如果该数据文件所在的表空间是只读的话,数据文件文件头的start scn和控制文件中datafile checkpoint不会被更新。

 

我们看下日志文件的情况:

SQL> select * from v$log;

 

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS

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

FIRST_CHANGE# FIRST_TIME

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

         1          1         13   52428800          1 YES INACTIVE

       927180 10-JUL-09

 

         2          1         15   52428800          1 NO  CURRENT

       991804 13-JUL-09

 

         3          1         14   52428800          1 YES INACTIVE

       966433 12-JUL-09

 

我们可以看到,当前的日志文件是2first_change991804F223C)。我们在看一下日志文件2的转储

SQL> alter system dump logfile '/export/home/oracle/oradata/uep/redo02.log';

 

System altered.

打开转储出来的文件,可以看到

DUMP OF REDO FROM FILE '/export/home/oracle/oradata/uep/redo02.log'

 Opcodes *.*

 RBAs: 0x000000.00000000.0000 thru 0xffffffff.ffffffff.ffff

 SCNs: scn: 0x0000.00000000 thru scn: 0xffff.ffffffff

 Times: creation thru eternity

 FILE HEADER:

        Compatibility Vsn = 169869824=0xa200200

        Db ID=3312617616=0xc5728890, Db Name='UEP'

        Activation ID=3312619408=0xc5728f90

        Control Seq=701=0x2bd, File size=102400=0x19000

        File Number=2, Blksiz=512, File Type=2 LOG

 descrip:"Thread 0001, Seq# 0000000015, SCN 0x0000000f223c-0xffffffffffff"

 thread: 1 nab: 0xffffffff seq: 0x0000000f hws: 0x2 eot: 1 dis: 0

 resetlogs count: 0x29266e12 scn: 0x0000.0008187f (530559)

 resetlogs terminal rcv count: 0x0 scn: 0x0000.00000000

 prev resetlogs count: 0x23696b6f scn: 0x0000.00000001 (1)

 prev resetlogs terminal rcv count: 0x0 scn: 0x0000.00000000

 Low  scn: 0x0000.000f223c (991804) 07/13/2009 18:57:57

 Next scn: 0xffff.ffffffff 01/01/1988 00:00:00

 Enabled scn: 0x0000.0008187f (530559) 06/24/2009 13:26:42

 Thread closed scn: 0x0000.000f223c (991804) 07/13/2009 18:57:57

 

我们看到,这里的low scn就是first_change。还可以看到next scn是个无穷大的数字。

 

这时候,我们通过命令执行一次checkpoint

SQL> alter system switch logfile;

 

System altered.

 

SQL> select * from v$log;

 

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS

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

FIRST_CHANGE# FIRST_TIME

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

         1          1         16   52428800          1 NO  CURRENT

       996605 13-JUL-09

 

         2          1         15   52428800          1 YES INACTIVE

       991804 13-JUL-09

 

         3          1         14   52428800          1 YES INACTIVE

       966433 12-JUL-09

 

可以看到,这时候日志文件2状态时inactive,数据库在使用日志文件1。日志文件1first_change应该与控制文件的系统scn,数据文件scn和数据文件文件头的scn相等,我们验证一下:

  1* select checkpoint_change# from v$datafile

SQL> /

 

CHECKPOINT_CHANGE#

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

            996605

            996605

            996605

            996605

            996605

            996605

 

6 rows selected.

 

  1* select checkpoint_change# from v$database

SQL> /

 

CHECKPOINT_CHANGE#

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

            996605

 

 

  1  select checkpoint_change#

  2* from v$datafile_header

SQL> /

 

CHECKPOINT_CHANGE#

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

            996605

            996605

            996605

            996605

            996605

            996605

 

6 rows selected.

 

可见,在执行过checkpoint之后,next scn更新了控制文件的系统scn,数据文件scn和数据文件文件头的启动scn

 

如果数据正常关闭的话,在关闭之前会做一个checkpoint操作,将log file中的数据写入数据文件中,将控制文件,数据文件的scn更新为最新的scn

当数据库启动时,oracle会检查控制文件中每个datafile checkpoint scn和数据文件文件头的启动scn是否相等,再检查每个datafile checkpoint scnstop scn是否相等。

如发现不同,则从redo log中找到丢失的scn,重新写入数据文件中进行恢复。

 

 

几个检查点SCN号的关系
1)       
几个检查点SCN都相同:在数据库打开并运行之后,控制文件中的系统检查点SCN、控制文件中的数据文件检查点SCN及每个数据文件头中的启动SCN都是相同的,控制文件中的每个数据文件的终止SCN都是NULL
2)       
数据库正常关闭时,系统会执行一个检查点动作,这时所有数据文件的 终止SCN号会设置为数据文件头的那个启动SCN。数据库重新启动时,Oracle将数据文件头中的启动SCN与数据文件检查点SCN比较,如果这两个值匹配,Oracle接下来再比较数据文件头中的SCN和控制文件中数据文件的终止SCN,如果这个值也匹配,就意味着所有数据块已经提交,因此数据库不需要进行恢复,此时数据库直接打开。当所有的数据文件都打开之后,终止SCN再次被设置为NULL,表示数据文件已经打开并能够正常使用了。
3)       
数据库非正常关闭(或称为实例崩溃)时,终止SCN不会被设置,依然为NULL,这可以通过把数据库启动至mount状态查询出来。这样Oracle通过这个信息就可以知道实例上次运行时崩溃了,检查点没有执行。这样重新启动时,Oracle会执行实例恢复工作,即先执行前滚、回滚操作,再把数据库打开。
4)       
数据文件检查点SCN及系统检查点SCN比文件头启动SCN大:这时的情况是:系统发生介质故障,数据文件被以前的备份代替,控制文件中的数据文件检查点SCN肯定比文件头中的启动SCN要大,这样Oracle就知道要对这个文件进行介质恢复。这时要通过下面语句恢复数据库:
recover database ……
5)       
系统检查点SCN比数据文件SCN及文件头启动SCN大:
有些表空间是只读的,这时控制文件中的系统检查点SCN号会不断增长,而数据文件SCN号和文件头中的启动SCN号会停止更新(直到表空间又设置为可读写),显然这时系统检查点SCN号会大于数据文件SCN和文件头启动SCN
6)       
系统检查点SCN及数据文件SCN比文件头启动SCN小:
在数据库恢复时,控制文件可能不是最新的,即把一个较早的控制文件还原为当前的控制文件,然后再执行恢复操作,这时控制文件中的系统检查点SCN和数据文件SCN可能比文件头的启动SCN小。这时恢复数据库要用下面命令:
recover database using Backup Controlfile
或其他的恢复语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值