SCN

关于各个SCN

 

SCN(System Change Number),也就是通常所说的系统改变号,是数据库中非常重要的一个数据结构。

SCN用以标识数据库在某个确切时刻提交的版本。在事务提交时,它被赋予一个唯一的标识事务的SCN。SCN同时被作为Oracle数据库的内部时钟机制,可被看做逻辑时钟,每个数据库都有一个全局的SCN生成器。

作为数据库内部的逻辑时钟,数据库事务依SCN而排序,Oracle也依据SCN来实现一致性读(Read Consistency)等重要数据库功能。另外对于分布式事务(Distributed Transactions),SCN也极为重要,这里不做更多介绍。

SCN在数据库中是唯一的,并随时间而增加,但是可能并不连贯。除非重建数据库,SCN的值永远不会被重置为0.

一直以来,对于SCN有很多争议,很多人认为SCN是指System Commit Number,而通常SCN在提交时才变化,所以很多时候,这两个名词经常在文档中反复出现。即使在Oracle的官方文档中,SCN也常以System Change/Commit Number两种形式出现。

到底是哪个词其实不是很重要,重要的是需要知道SCN是Oracle内部的时钟机制,Oracle通过SCN来维护数据库的一致性,并通过SCN实施Oracle至关重要的恢复机制。

SCN在数据库中是无处不在,常见的事务表、控制文件、数据文件头、日志文件、数据块头等都记录有SCN值。

冠以不同前缀,SCN也有了不同的名称,如检查点SCN(Checkpint SCN)、Resetlogs SCN等。

 

~~~~~~~~~~~~~~~~~~~~~

  • 控制文件中记录的SCN:
        系统检查点SCN(v$database.checkpoint_change#)
        数据文件检查点SCN(v$datafile.checkpoint_change#)
        数据文件结束SCN(v$datafile.last_change#)
        日志文件low scn和next scn
  • 数据文件中存在的SCN
        数据文件头SCN,启动SCN(v$datafile_header.checkpoint_change#)
        数据块SCN(块头,块尾)
  • 日志文件中记录的SCN
        日志文件头记录low scn和next scn
        日志文件change vector中有每个操作的SCN

1.系统SCN
    当一个checkpoint完成时,由CKPT后台进程将这个CHECKPOINT SCN更新到控制文件中

   1:      select checkpoint_change# from v$database;

2.数据文件SCN
    当一个检查点完成时,CKPT进程会将每个数据文件的CHECKPOINT SCN分别更新到控制文件中,每个数据文件对应一条记录.这个值与系统检查点SCN一致.

   1:      select name,checkpoint_change# from v$datafile;

3.启动SCN(数据文件头SCN)
    Oracle把这个检查点的scn存储在每个数据文件的文件头中,这个值也称为启动scn,因为在数据库实例启动时,检查是否需要执行数据库恢复。

   1:      select name,checkpoint_change# from v$datafile_header;

4.结束SCN
    在数据库正常运行过程中,这个SCN值为NULL,也可以理解为无穷大.
    当数据库关闭时,会发生一次完全CHECKPOIN,这次检查点除了会更新上面三个SCN外,还会更新控制文件中记录的数据文件的结束SCN.
    下一次启动时,会检查datafile header SCN ?= stop scn以确定是否需要恢复

   1:      select name,last_change# from v$datafile;

数据库正常运行过程中

系统SCN、数据文件SCN、数据文件头SCN 这三个SCN值都是相同的,
    当系统发生checkpoint时,
    1.触发DBWR进程将DB CACHE中的dirty block写入到数据文件;
    2.而DBWR进程在写数据文件之前,会查看这些dirty block相关的redo entris是否已经写入到日志文件;
    3.如果相关redo还没有写入到日志文件,则通知LGWR进程将redo entris写入到日志文件;
    4.当LGWR与DBWR进程都写完之后,CKPT进程将这个CHECKPOINT SCN值更新到控制文件中的系统SCN、数据文件SCN、还有更新这个CHECKPOINT SCN到各个数据文件头
    5.至此,CHECKPOINT完成,此次CHECKPOIN之前的数据与redo信息都已经写入到物理文件中,instance recovery时就不需要恢复在此之前的redo信息。

数据库正常关闭时
    发生一次完全CHECKPOIN
    这次CHECKPOIN除了会完成上面动作之外,还会更新控制文件中各个数据文件相关的STOP SCN,这样,下次启动时,系统SCN、数据文件SCN、数据文件头SCN、数据文件STOP SCN都是一致的,也就是说不存在数据丢失,就不需要恢复。

数据库非正常关闭时
    比如shutdown abort
    这时,并不会产生CHECKPOIN,而是直接关掉instance
    因为没有发生CHECKPOIN,所以,控制文件,数据文件头中记录的信息还是关闭操作前最近一次CHECKPOINT更新的记录。
    这时,系统SCN、DATAFILE SCN、DATAFILE_HEADER SCN是相同的(关闭前最后一次CHECKPOIN更新操作),
    而,数据文件的STOP SCN为NULL,
    下次打开数据库时,就需要完成恢复操作

数据库打开时
    ORACLE会比对数据文件头SCN(启动SCN)与控制文件中记录的数据文件SCN
    如果这两个值相同,则比较数据文件头SCN(启动SCN)与控制文件中记录的数据文件STOP SCN
    如果这两个值也相同,则证明上次关闭是正常关闭,所有已经提交的操作都已经写入到数据文件,不需要恢复操作
    这时,数据库正常打开
    当所有的数据文件都正常打开,ORACLE会更新控制文件中记录的数据文件STOP SCN为NULL
    完成上次操作之后,数据库才算完全打开,完成了整个OPEN动作,为用户提供服务

一般情况下,发生实例失败时
    datafile_header SCN (in datafile header) = datafile SCN(in controlfile) = system SCN (in controlfile)
    datafile_header SCN (in datafile header)!= stop SCN(in controlfile)
    因为发生instance failur,关闭时没有发生CHECKPOINT,所以stop SCN为NULL(也可以说无穷大),这时,就需要实例恢复,
    在datafile header中有RBA的记录,RBA 包含了日志序号、block number 、slot number , 这样ORACLE就可以直接定位到日志文件(归档日志文件)和具体的位置
    之后,会比对datafile_header SCN与change vector中记录的SCN,
    如果datafile_header SCN < 日志的change vector SCN,则恢复这些redo.
    完成redo操作(这个过程中,undo表空间也在完成redo操作)
    redo操作完成之后,会根据undo中的记录完成undo操作。

需要介质恢复情况下
    datafile_header SCN (START SCN ) != datafile SCN (record in controlfile)

判断是否需要恢复,需要实例恢复还是介质恢复:

    datafile_header SCN ?= datafile SCN        (record in controlfile)
    datafile_header SCN ?= datafile STOP SCN   (record in controlfile)

2.SCN的获取方式

可以通过如下几种方式获得数据库的当前或近似SCN。

(1) 从Oracle 9i开始。

可以使用dbms_flashback.get_system_change_number来获得:

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

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

888266

(2) Oracle 9i前。

可以通过查询x$ktuxe获得系统最接近当前值的SCN:

X$ktuxe的含义是[k]ernel [T]ransaction [U]ndo Transa[x]tion [E]ntry(table)

SQL>select max(ktuxecnw*power(2,32)+ktuxescnb) from x$ktuxe;

MAX(KTUXESCNW*POWER(2,32)+KTUXESCNB)

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

28848232

 

3.SCN的进一步说明

系统当前SCN并不是在任何的数据库操作时都会改变,SCN通常在事务提交或回滚时改变。在控制文件、数据文件头、数据库、日志文件头、日志文件change vector中都有SCN,但其作用各不相同。

(1) 数据文件头中包含了该数据文件的Checkpoint SCN,表示该数据文件最近一次执行检查点操作时的SCN

从控制文件的dump文件中,可以得到一下内容:

DATA FILE #1:

(name #7) /opt/ora10g/oradata/ORCL/system01.dbf

creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

tablespace 0, index=1 krfil=1 prev_file=0

unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

Checkpoint cnt:106 scn: 0x0000.000d845f 11/14/2011 15:24:50

Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

……

对于每一个数据文件都包含一个这样的条目,记录该文件的检查点SCN的值以及检查点发生的时间,这里的Checkpint SCN、Stop SCN以及Checkpoint CNT都是非常重要的数据结构,我们将会在下面检查点部分详细介绍。

同样可以通过命令转储数据文件头,观察其具体信息及检查点记录等,从跟踪文件中摘取system表空间的记录作为参考:

***************************************************************************

DATA FILE RECORDS

***************************************************************************

(size = 428, compat size = 428, section max = 100, section in-use = 4,

last-recid= 53, old-recno = 0, last-recno = 0)

(extent = 1, blkno = 11, numrecs = 100)

DATA FILE #1:

(name #7) /opt/ora10g/oradata/ORCL/system01.dbf

creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

tablespace 0, index=1 krfil=1 prev_file=0

unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

Checkpoint cnt:106 scn: 0x0000.000d845f 11/14/2011 15:24:50

Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

thread:0 rba:(0x0.0.0)

enabled threads: 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Offline scn: 0x0000.0006ce7a prev_range: 0

Online Checkpointed at scn: 0x0000.0006ce7b 11/10/2011 22:40:23

thread:1 rba:(0x1.2.0)

enabled threads: 01000000 00000000 00000000 00000000 00000000 00000000

Hot Backup end marker scn: 0x0000.00000000

aux_file is NOT DEFINED

(2) 日志文件头包含了Low SCN 和Next SCN。

Low SCN和 Next SCN这两个SCN表示该日志文件包含介于Low SCN到Next SCN的重做信息,对于Current的日志文件(当前正在被使用的Redo Logfile),其最终SCN不可知,所以Next SCN被置为无穷大,也就是ffffffff。

来看一下日志文件的情况:

SQL> select * from v$log;

GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM

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

1 1 35 52428800 1 NO CURRENT 881890 14-NOV-11

2 1 33 52428800 1 YES INACTIVE 836815 12-NOV-11

3 1 34 52428800 1 YES INACTIVE 858362 12-NOV-11

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

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

889346

SQL> alter system switch logfile;

System altered.

SQL> select * from v$log;

GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM

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

1 1 35 52428800 1 YES ACTIVE 881890 14-NOV-11

2 1 36 52428800 1 NO CURRENT 889353 14-NOV-11

3 1 34 52428800 1 YES INACTIVE 858362 12-NOV-11

可以看到,SCN 889346显然位于Log Group#为1的日志文件中,该日志文件包含了SCN自881890 至889353 的Redo信息。Oracle在进行恢复时,就需要根据低SCN和高SCN来确定需要的恢复信息位于哪一个日志或归档文件中。

如果通过控制文件转储,可以在控制文件中找到关于日志文件的信息:

SQL> alter session set events 'immediate trace name redohdr level 10';

Session altered.

 

LOG FILE #1:

(name #3) /opt/ora10g/oradata/ORCL/redo01.log

Thread 1 redo log links: forward: 2 backward: 0

siz: 0x19000 seq: 0x00000026 hws: 0x1 bsz: 512 nab: 0xffffffff flg: 0x8 dup: 1

Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.000de15c

Low scn: 0x0000.000def9a 11/16/2011 16:06:06

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

LOG FILE #2:

(name #2) /opt/ora10g/oradata/ORCL/redo02.log

Thread 1 redo log links: forward: 3 backward: 1

siz: 0x19000 seq: 0x00000024 hws: 0x4 bsz: 512 nab: 0x5c6 flg: 0x1 dup: 1

Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.000d74e2

Low scn: 0x0000.000d9209 11/14/2011 16:57:08

Next scn: 0x0000.000de15c 11/16/2011 15:01:07

LOG FILE #3:

(name #1) /opt/ora10g/oradata/ORCL/redo03.log

Thread 1 redo log links: forward: 0 backward: 2

siz: 0x19000 seq: 0x00000025 hws: 0x3 bsz: 512 nab: 0x37e3 flg: 0x1 dup: 1

Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.000d9209

Low scn: 0x0000.000de15c 11/16/2011 15:01:07

Next scn: 0x0000.000def9a 11/16/2011 16:06:06

可以注意到,Log File 1是当前的日志文件,该文件拥有的Next SCN是无穷大。

同样,可以通过直接dump日志文件的方式来进行转储;

SQL> select * from v$logfile;

GROUP# STATUS TYPE MEMBER

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

3 ONLINE /opt/ora10g/oradata/ORCL/redo03.log

2 ONLINE /opt/ora10g/oradata/ORCL/redo02.log

1 ONLINE /opt/ora10g/oradata/ORCL/redo01.log

SQL> alter system dump logfile '/opt/ora10g/oradata/ORCL/redo01.log';

System altered.

DUMP OF REDO FROM FILE '/opt/ora10g/oradata/ORCL/redo01.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 = 169869568=0xa200100

Db ID=1294662348=0x4d2afacc, Db Name='ORCL'

Activation ID=1294635980=0x4d2a93cc

Control Seq=953=0x3b9, File size=102400=0x19000

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

descrip:"Thread 0001, Seq# 0000000038, SCN 0x0000000def9a-0xffffffffffff"

thread: 1 nab: 0xffffffff seq: 0x00000026 hws: 0x1 eot: 1 dis: 0

resetlogs count: 0x2db5af57 scn: 0x0000.0006ce7b (446075)

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

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

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

Low scn: 0x0000.000def9a (913306) 11/16/2011 16:06:06

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

Enabled scn: 0x0000.0006ce7b (446075) 11/10/2011 22:40:23

Thread closed scn: 0x0000.000def9a (913306) 11/16/2011 16:06:06

Disk cksum: 0x5987 Calc cksum: 0x5987

Terminal recovery stop scn: 0x0000.00000000

Terminal recovery 01/01/1988 00:00:00

Most recent redo scn: 0x0000.00000000

Largest LWN: 0 blocks

End-of-redo stream : No

Unprotected mode

Miscellaneous flags: 0x0

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16920491/viewspace-744757/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/16920491/viewspace-744757/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值