ITPub博客

首页 > 数据库 > Oracle > 学习什么是SCN

学习什么是SCN

Oracle 作者:bitifi 时间:2017-02-10 10:42:30 0 删除 编辑


--只能算半原创吧,理论主要来自ITPUB论坛的“听海日志”,自己做的实验来进行理解和验证

一、            什么是SCN
Concepts中是这样描述SCN的:

A system change number (SCN) is alogical, internal timestamp used by Oracle Database. SCNs order events thatoccur within the database, which is necessary to satisfy the ACID properties ofa transaction. Oracle Database uses SCNs to mark the SCN before which allchanges are known to be on disk so that recovery avoids applying unnecessaryredo. The database also uses SCNs to mark the point at which no redo exists fora set of data so that recovery can stop.

怎么理解这个“SCN(系统变更号)是供Oracle数据库使用的一个逻辑的、内部的时间戳”呢?要理解这个先需要理解Oracle中的事务(Transaction)和数据一致性(Data Consistency)的概念。

先说说数据一致性的概念。数据一致性指的是数据的可用性。比如说管理一个财务的系统,需要从A账户将100元转入到B账户,正常的操作是从A账户减去100元,然后给B账户加上100元,如果这两步操作都正常完成了,那我们可以说完成转账操作之后的数据是一致可用的;但是如果在操作的过程中出了问题,A账户的100元给减掉了,但是B账户却没有加上100元,这样的情况下产生的结果数据就有问题了,因为部分操作的失败导致了数据的不一致而不可用,在实际中肯定是要避免这种让数据不一致的情况发生的。在Oracle数据库中,保证数据一致性的方法就是事务。

事务是一个逻辑的、原子性的作业单元,通常由一个或者是多个SQL组成,一个事务里面的所有SQL操作要么全部失败回滚(Rollback),要么就是全部成功提交(Commit)。就像上面转账的例子,为保证数据的一致性,就需要将转账的两步操作放在一个事务里面,这样不管哪个操作失败了,都需要将所有已进行的操作回滚,以保证数据的可用性。进行事务管理是数据库区别于别的文件系统的一个最主要的特征,在数据库中事务最主要的作用就是保证了数据的一致性,每次事务的提交都是将数据库从一种一致性的状态带入到另外一种一致性的状态中,SCN就是用来对数据库的每个一致状态进行标记的,每当数据库进入到一个新的一致的状态,SCN就会加1,也就是每个提交操作之后,SCN都会增加。也许你会想为什么不直接记录事务提交时候的时间戳呢?这里面主要是涉及了两个问题,一个是时间戳记录的精度有限,再一个就是在分布式系统中记录时间戳会存在系统时钟同步的问题,详细的讨论可以查看Ordering Events in Oracle。

SCN在数据库中是一个单一的不断的随着数据库一致性状态的改变而自增的序列。正如一个时间戳代表着时间里面的某一个固定的时刻点一样,每一个SCN值也代表着数据库在运行当中的一个一致性的点,大的SCN值所对应的事务总是比小SCN值的事务发生的更晚。因此把SCN说成是Oracle数据库的逻辑时间戳是很恰当的。

二、            SCN概述 

SCN是当Oracle数据库更新后,由DBMS去自动维护累积递增的一个数字。通常看文章的时候能看到各种类型的SCN,但是严格来说SCN是没有分类的,之所以会有不同类型的SCN并不是说这些SCN的概念不一样,而是说不同分类的SCN代表的意义不一样,不管什么时候SCN所指代的都是数据库的某个一致性的状态。就像我们给一天中的某个时间点定义上班时间、另外的某个时间点定义成下班时间一样,数据库Checkpoint发生点的SCN被称为Checkpoint SCN,仅此而已。Oracle数据库中一共有4种SCN分别为:

?系统检查点SCN (System Checkpoint SCN)

?文件检查点SCN (Datafile Checkpoint SCN)

?结束SCN (Stop SCN)

?数据文件头SCN (Start SCN)

前面3个SCN存在于控制文件中,最后一种则存在于数据文件的文件头中。

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

在控制文件中,System Checkpoint SCN是针对整个数据库全局的,因而只存在一个Datafile Checkpoint SCN和Stop SCN是针对每个数据文件的,因而一个数据文件就对应在控制文件中存在一份Datafile Checkpoint SCN和Stop SCN。在数据库正常运行期间,Stop SCN(通过视图v$datafile的字段last_change#可以查询)是一个无穷大的数字或者NULL。

 

1.        系统检查点SCN(System Checkpoint SCN)- 存于控制文件

系统检查点SCN位于控制文件中,当检查点进程启动时(ckpt),Oracle就把系统检查点的SCN存储到控制文件中。该SCN是全局范围的(比如日志切换),当发生文件级别的SCN时,例如将表空间置为只读、begin backup或将某个数据文件设置为offline等,则不会更新系统检查点SCN。

select checkpoint_change# from v$database;

SYS@PROD>select trim(checkpoint_change#) cc# from v$database;

 

CC#

------

714857

 

2.        文件检查点SCN(Datafile Checkpoint SCN)- 存于控制文件

 

SYS@PROD>alter tablespace tbs_tommie offline;

 

Tablespace altered.

 

SYS@PROD>select trim(file#) f#,name,trim(checkpoint_change#) cc#, trim(last_change#) lc# from v$datafile;

 

F NAME                                                CC#    LC#

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

1 /u01/app/oracle/oradata/PROD/disk1/system001.dbf    714857

2 /u01/app/oracle/oradata/PROD/disk1/undotbs01.dbf    714857

3 /u01/app/oracle/oradata/PROD/disk1/sysaux01.dbf     714857

4 /u01/app/oracle/oradata/PROD/disk1/example1.dbf     714857

5 /u01/app/oracle/oradata/PROD/disk1/indx1.dbf        714857

6 /u01/app/oracle/oradata/PROD/disk1/tools1.dbf       714857

7 /u01/app/oracle/oradata/PROD/disk1/users1.dbf       714857

8 /u01/app/oracle/oradata/PROD/disk1/oltp1.dbf        714857

9 /u01/app/oracle/oradata/PROD/disk3/tbs_tommie01.dbf 715270 715270

 

9 rows selected.

 

SYS@PROD>alter tablespace tbs_tommie online;

 

Tablespace altered.

 

SYS@PROD>select trim(file#) f#,name,trim(checkpoint_change#) cc#, trim(last_change#) lc# from v$datafile;

 

F NAME                                                CC#    LC#

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

1 /u01/app/oracle/oradata/PROD/disk1/system001.dbf    714857

2 /u01/app/oracle/oradata/PROD/disk1/undotbs01.dbf    714857

3 /u01/app/oracle/oradata/PROD/disk1/sysaux01.dbf     714857

4 /u01/app/oracle/oradata/PROD/disk1/example1.dbf     714857

5 /u01/app/oracle/oradata/PROD/disk1/indx1.dbf        714857

6 /u01/app/oracle/oradata/PROD/disk1/tools1.dbf       714857

7 /u01/app/oracle/oradata/PROD/disk1/users1.dbf       714857

8 /u01/app/oracle/oradata/PROD/disk1/oltp1.dbf        714857

9 /u01/app/oracle/oradata/PROD/disk3/tbs_tommie01.dbf 715288

 

9 rows selected.

 

可以看到9号文件也就是tbs_tommie表空间所属的文件SCN值和其他文件不一致,且比系统检查点的SCN要大(因为这个数据文件最后被操作,其他数据文件没有变动)。

 

3.        结束SCN(Stop SCN)- 存于控制文件

见二中的表空间tbs_tommie的数据文件的last_change#,offline时有值,online后又为NULL。

另:将数据库至于mount状态,由于该状态下所有的数据文件都不可写,故mount状态下所有的数据文件都具有结束SCN。

SYS@PROD>shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SYS@PROD>startup mount

ORACLE instance started.

 

Total System Global Area  314572800 bytes

Fixed Size                  1219184 bytes

Variable Size              75498896 bytes

Database Buffers          234881024 bytes

Redo Buffers                2973696 bytes

Database mounted.

SYS@PROD>select trim(file#) f#,name,trim(checkpoint_change#) cc#, trim(last_change#) lc# from v$datafile;

 

F NAME                                                CC#    LC#

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

1 /u01/app/oracle/oradata/PROD/disk1/system001.dbf    715634 715634

2 /u01/app/oracle/oradata/PROD/disk1/undotbs01.dbf    715634 715634

3 /u01/app/oracle/oradata/PROD/disk1/sysaux01.dbf     715634 715634

4 /u01/app/oracle/oradata/PROD/disk1/example1.dbf     715634 715634

5 /u01/app/oracle/oradata/PROD/disk1/indx1.dbf        715634 715634

6 /u01/app/oracle/oradata/PROD/disk1/tools1.dbf       715634 715634

7 /u01/app/oracle/oradata/PROD/disk1/users1.dbf       715634 715634

8 /u01/app/oracle/oradata/PROD/disk1/oltp1.dbf        715634 715634

9 /u01/app/oracle/oradata/PROD/disk3/tbs_tommie01.dbf 715634 715634

 

9 rows selected.

 

SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

715634

 

因数据库先做了shutdown immediate,属正常关闭,因此checkpoint_change#=last_change#,即System Checkpoint SCN=Datafile Checkpoint SCN=Stop SCN

 

继续打开数据库再看

SYS@PROD>alter database open;

 

Database altered.

 

SYS@PROD>select trim(checkpoint_change#) cc# from v$database;

 

CC#

------

715635

 

SYS@PROD>select trim(file#) f#,name,trim(checkpoint_change#) cc#, trim(last_change#) lc# from v$datafile;

 

F NAME                                                CC#    LC#

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

1 /u01/app/oracle/oradata/PROD/disk1/system001.dbf    715635

2 /u01/app/oracle/oradata/PROD/disk1/undotbs01.dbf    715635

3 /u01/app/oracle/oradata/PROD/disk1/sysaux01.dbf     715635

4 /u01/app/oracle/oradata/PROD/disk1/example1.dbf     715635

5 /u01/app/oracle/oradata/PROD/disk1/indx1.dbf        715635

6 /u01/app/oracle/oradata/PROD/disk1/tools1.dbf       715635

7 /u01/app/oracle/oradata/PROD/disk1/users1.dbf       715635

8 /u01/app/oracle/oradata/PROD/disk1/oltp1.dbf        715635

9 /u01/app/oracle/oradata/PROD/disk3/tbs_tommie01.dbf 715635

 

9 rows selected.

 

同样数据库保持了一致性,即System Checkpoint SCN=Datafile Checkpoint SCN,Stop SCN=NULL。

 

4.        数据文件头SCN(Start SCN)- 存于数据文件的文件头

不同于上述的SCN数据文件开始SCN记录在每个数据文件中。当发生系统及文件级别的检查点后,不仅将这时的SCN号记录在控制文件中,同样也记录在数据文件中。查询数据文件头SCN的命令如下:

sys@ORCL>select file#,CHECKPOINT_CHANGE# from v$datafile_header;

 

SYS@PROD>select trim(file#) f#, trim(checkpoint_change#) cc# from v$datafile_header;

 

F CC#

- ------

1 715635

2 715635

3 715635

4 715635

5 715635

6 715635

7 715635

8 715635

9 715635

 

9 rows selected.

 

此时Start SCN=System Checkpoint SCN=Datafile Checkpoint SCN

 

三、            SCN相关概念

1.        Redo log中的high SCN和low SCN

Oracle的Redo log会顺序纪录数据库的各个变化。一组redo log文件写满后,会自动切换到下一组redo log文件。则上一组redo log的high SCN就是下一组redo log的low SCN。在current log中high SCN为无穷大。可通过查询v$log_history查看 low SCN和 high SCN:

 

SYS@PROD>select recid,sequence#,first_change#,next_change# from v$log_history;

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

         1         36        597766       598183

         2          1        598449       638186

         3          2        638186       638842

         4          3        638842       638854

         5          4        638854       638937

         6          5        638937       638948

         7          6        638948       639692

         8          7        639692       639694

         9          8        639694       639697

        10          9        639697       639699

        11         10        639699       639702

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        12         11        639702       639970

        13         12        639970       639972

        14         13        639972       639975

        15         14        639975       639977

        16         15        639977       639979

        17         16        639979       641997

        18         17        641997       644653

        19         18        644653       644655

        20         19        644655       644658

        21          1        644659       648896

        22          2        648896       648898

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        23          3        648898       648902

        24          4        648902       648904

        25          1        648905       669544

        26          2        669544       670151

        27          3        670151       670186

        28          4        670186       673454

        29          5        673454       673459

        30          6        673459       711108

        31          7        711108       714855

        32          8        714855       714857

 

32 rows selected.

 

2.        查看currnet redolog中的high SCN

SYS@PROD>select vf.member, v.status, v.first_change# from v$logfile vf, v$log v where vf.group#=v.group# and v.status='CURRENT';

 

MEMBER

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

STATUS                           FIRST_CHANGE#

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

/u01/app/oracle/oradata/PROD/disk1/redo301.log

CURRENT                                 714857

 

/u01/app/oracle/oradata/PROD/disk2/redo302.log

CURRENT                                 714857

 

/u01/app/oracle/oradata/PROD/disk3/redo303.log

CURRENT                                 714857

 

 

MEMBER

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

STATUS                           FIRST_CHANGE#

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

/u01/app/oracle/oradata/PROD/disk4/redo304.log

CURRENT                                 714857

 

此时可以和一中的记录进行对比,一里的最后一条记录recid=32,其last_change#=当前日志组的first_change#。

再看如下:

SYS@PROD>alter system dump logfile '/u01/app/oracle/oradata/PROD/disk1/redo301.log';

 

System altered.

 

SYS@PROD>show parameter user_dump;

 

NAME                                 TYPE

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

VALUE

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

user_dump_dest                       string

/u01/app/oracle/admin/PROD/udump

 

打开转储的trace文件:

-rw-r-----  1 oracle oinstall 3835232  1月 28 11:36 prod_ora_12847.trc

[oracle@odd-oelr4u8 udump]$ date

二  1月 28 11:38:00 CST 2014

[oracle@odd-oelr4u8 udump]$ pwd

/u01/app/oracle/admin/PROD/udump

[oracle@odd-oelr4u8 udump]$ vi prod_ora_12847.trc

Dump file /u01/app/oracle/admin/PROD/udump/prod_ora_12847.trc

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production

With the Partitioning, Oracle Label Security, OLAP and Data Mining options

ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1

System name:    Linux

Node name:      odd-oelr4u8

Release:        2.6.9-89.0.0.0.1.ELsmp

Version:        #1 SMP Tue May 19 04:23:49 EDT 2009

Machine:        i686

Instance name: PROD

Redo thread mounted by this instance: 1

Oracle process number: 26

Unix process pid: 12847, image: oracle@odd-oelr4u8 (TNS V1-V3)

 

*** 2014-01-28 11:25:37.360

*** SERVICE NAME:(SYS$USERS) 2014-01-28 11:25:37.360

*** SESSION ID:(289.3) 2014-01-28 11:25:37.360

tkcrrsarc: (WARN) Failed to find ARCH for message (message:0x1)

tkcrrpa: (WARN) Failed initial attempt to send ARCH message (message:0x1)

*** 2014-01-28 11:36:55.032

 

DUMP OF REDO FROM FILE '/u01/app/oracle/oradata/PROD/disk1/redo301.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=248672105=0xed26f69, Db Name='PROD'

        Activation ID=249629221=0xee10a25

        Control Seq=2332=0x91c, File size=204800=0x32000

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

 descrip:"Thread 0001, Seq# 0000000009, SCN 0x0000000ae869-0xffffffffffff"

 thread: 1 nab: 0xffffffff seq: 0x00000009 hws: 0x4 eot: 1 dis: 0

 resetlogs count: 0x31ef36d5 scn: 0x0000.0009e6c9 (648905)

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

 prev resetlogs count: 0x31ef23a6 scn: 0x0000.0009d633 (644659)

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

 Low  scn: 0x0000.000ae869 (714857) 01/28/2014 11:05:48 -- 这里对应current log的first_change#

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

 Enabled scn: 0x0000.0009e6c9 (648905) 01/25/2014 07:18:45

 Thread closed scn: 0x0000.000aeb72 (715634) 01/28/2014 11:22:29

 Disk cksum: 0xe808 Calc cksum: 0xe808

 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

 Thread internal enable indicator: thr: 0, seq: 0 scn: 0x0000.00000000

 

 

redo log中当前系统的SCN记录当前最新的数据库SCN值可通过如下命令查看:

SYS@PROD>select dbms_flashback.get_system_change_number from dual;

 

GET_SYSTEM_CHANGE_NUMBER

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

                  716088

 

 

如果需要进行实例恢复,则需恢复的记录为714857至716088中redo log中的记录。

 

且get_system_change_number一直在变化:

SYS@PROD>select dbms_flashback.get_system_change_number from dual;

 

GET_SYSTEM_CHANGE_NUMBER

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

                  716264

 

SYS@PROD>select dbms_flashback.get_system_change_number from dual;

 

GET_SYSTEM_CHANGE_NUMBER

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

                  716265

 

原因在于:there are things in the background going on -- AQ, SMON, Job queues -- maybe

even other users.  The "idle" database is actually very active.

 

SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635

基本不变

那么这两种方法取出的值有什么区别呢?GET_SYSTEM_CHANGE_NUMBER又与哪些值有联系呢?和Datafile Checkpoint SCN还有Stop SCN有什么联系呢?

3.        日志切换或发生Checkpoint

当日志切换或发生checkpoint时,从Low SCN(first_change#)到High SCN(next_change#)之间的所有redo记录的数据就被DBWn进程写入数据文件中,如下查询:SYS@PROD>select recid,sequence#,first_change#,next_change# from v$log_history;

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

         1         36        597766       598183

         2          1        598449       638186

         3          2        638186       638842

         4          3        638842       638854

         5          4        638854       638937

         6          5        638937       638948

         7          6        638948       639692

         8          7        639692       639694

         9          8        639694       639697

        10          9        639697       639699

        11         10        639699       639702

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        12         11        639702       639970

        13         12        639970       639972

        14         13        639972       639975

        15         14        639975       639977

        16         15        639977       639979

        17         16        639979       641997

        18         17        641997       644653

        19         18        644653       644655

        20         19        644655       644658

        21          1        644659       648896

        22          2        648896       648898

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        23          3        648898       648902

        24          4        648902       648904

        25          1        648905       669544

        26          2        669544       670151

        27          3        670151       670186

        28          4        670186       673454

        29          5        673454       673459

        30          6        673459       711108

        31          7        711108       714855

        32          8        714855       714857

 

32 rows selected.而CKPT进程则将所有数据文件(无论redo log中的数据是否影响到该数据文件)的文件头上记录的Start SCN(通过视图v$datafile_header的字段checkpoint_change#可以查询SYS@PROD>select trim(checkpoint_change#) from v$datafile_header;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635

715635

715635

715635

715635

715635

715635

715635

715635

 

9 rows selected.)更新为High SCN,同时将控制文件中的System Checkpoint SCN(通过视图v$database的字段checkpoint_change#可以查询SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635)、每个数据文件对应的DatafileCheckpoint(通过视图v$datafile的字段checkpoint_change#可以查询SYS@PROD>select trim(checkpoint_change#) from v$datafile;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635

715635

715635

715635

715635

715635

715635

715635

715635

 

9 rows selected.)也更新为High SCN。但是,如果该数据文件所在的表空间被设置为read-only时,数据文件的Start SCN和控制文件中DatafileCheckpoint SCN都不会被更新。

例子:

SYS@PROD>alter tablespace tbs_tommie read only;

 

Tablespace altered.

 

SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635

 

SYS@PROD>select trim(checkpoint_change#) from v$datafile;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635

715635

715635

715635

715635

715635

715635

715635

717444

 

9 rows selected.

然后我们做一个日志切换,再查询看一下变化:

日志切换前:

SYS@PROD>select recid,sequence#,first_change#,next_change# from v$log_history;

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

         1         36        597766       598183

         2          1        598449       638186

         3          2        638186       638842

         4          3        638842       638854

         5          4        638854       638937

         6          5        638937       638948

         7          6        638948       639692

         8          7        639692       639694

         9          8        639694       639697

        10          9        639697       639699

        11         10        639699       639702

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        12         11        639702       639970

        13         12        639970       639972

        14         13        639972       639975

        15         14        639975       639977

        16         15        639977       639979

        17         16        639979       641997

        18         17        641997       644653

        19         18        644653       644655

        20         19        644655       644658

        21          1        644659       648896

        22          2        648896       648898

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        23          3        648898       648902

        24          4        648902       648904

        25          1        648905       669544

        26          2        669544       670151

        27          3        670151       670186

        28          4        670186       673454

        29          5        673454       673459

        30          6        673459       711108

        31          7        711108       714855

        32          8        714855       714857

 

32 rows selected.

--日志切换

SYS@PROD>alter system switch logfile;

 

System altered.

--日志切换

SYS@PROD>alter system switch logfile;

 

System altered.

--再查询联机日志记录历史发现增加了两条记录

SYS@PROD>select recid,sequence#,first_change#,next_change# from v$log_history;

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

         1         36        597766       598183

         2          1        598449       638186

         3          2        638186       638842

         4          3        638842       638854

         5          4        638854       638937

         6          5        638937       638948

         7          6        638948       639692

         8          7        639692       639694

         9          8        639694       639697

        10          9        639697       639699

        11         10        639699       639702

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        12         11        639702       639970

        13         12        639970       639972

        14         13        639972       639975

        15         14        639975       639977

        16         15        639977       639979

        17         16        639979       641997

        18         17        641997       644653

        19         18        644653       644655

        20         19        644655       644658

        21          1        644659       648896

        22          2        648896       648898

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        23          3        648898       648902

        24          4        648902       648904

        25          1        648905       669544

        26          2        669544       670151

        27          3        670151       670186

        28          4        670186       673454

        29          5        673454       673459

        30          6        673459       711108

        31          7        711108       714855

        32          8        714855       714857

        33          9        714857       717474

        34         10        717474       717476

34 rows selected.

但是System Checkpoint SCN和Start SCN没有变化,为什么?

SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635

 

SYS@PROD>select trim(checkpoint_change#) from v$datafile;

 

TRIM(CHECKPOINT_CHANGE#)

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

715635

715635

715635

715635

715635

715635

715635

715635

717444—本来就不应该变化

 

9 rows selected.

但是再看下面:

SYS@PROD>alter tablespace tbs_tommie read write;

 

Tablespace altered.

 

SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

717476

 

SYS@PROD>select trim(checkpoint_change#) from v$datafile;

 

TRIM(CHECKPOINT_CHANGE#)

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

717476

717476

717476

717476

717476

717476

717476

717476

717569

 

9 rows selected.

 

继续看变化:

n  将表空间变为只读

SYS@PROD>alter tablespace tbs_tommie read only;

 

Tablespace altered.

n  查询System Checkpoint SCN无变化

SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

717476

n  查询Datafile Checkpoint SCN无变化

 

SYS@PROD>select trim(checkpoint_change#) from v$datafile;

 

TRIM(CHECKPOINT_CHANGE#)

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

717476

717476

717476

717476

717476

717476

717476

717476

717604

 

9 rows selected.

n  再把表空间变为可读写再查询一轮

 

SYS@PROD>alter tablespace tbs_tommie read write;

 

Tablespace altered.

n  查询Datafile Checkpoint SCN仍旧无变化

 

SYS@PROD>select trim(checkpoint_change#) from v$datafile;

 

TRIM(CHECKPOINT_CHANGE#)

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

717476

717476

717476

717476

717476

717476

717476

717476

717624

 

9 rows selected.

n  手工发起checkpoint

 

SYS@PROD>alter system checkpoint;

 

System altered.

n  Loghistory无变化

 

SYS@PROD>select recid,sequence#,first_change#,next_change# from v$log_history;

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

         1         36        597766       598183

         2          1        598449       638186

         3          2        638186       638842

         4          3        638842       638854

         5          4        638854       638937

         6          5        638937       638948

         7          6        638948       639692

         8          7        639692       639694

         9          8        639694       639697

        10          9        639697       639699

        11         10        639699       639702

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        12         11        639702       639970

        13         12        639970       639972

        14         13        639972       639975

        15         14        639975       639977

        16         15        639977       639979

        17         16        639979       641997

        18         17        641997       644653

        19         18        644653       644655

        20         19        644655       644658

        21          1        644659       648896

        22          2        648896       648898

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        23          3        648898       648902

        24          4        648902       648904

        25          1        648905       669544

        26          2        669544       670151

        27          3        670151       670186

        28          4        670186       673454

        29          5        673454       673459

        30          6        673459       711108

        31          7        711108       714855

        32          8        714855       714857

        33          9        714857       717474

 

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#

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

        34         10        717474       717476

 

34 rows selected.

n  查询System Checkpoint SCN发生了变化,变成了前面Datafile Checkpoint SCN里变化的表空间的SCN

 

SYS@PROD>select trim(checkpoint_change#) from v$database;

 

TRIM(CHECKPOINT_CHANGE#)

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

717642

n  查询Datafile Checkpoint SCN发生了变化,变成了前面Datafile Checkpoint SCN里变化的表空间的SCN

SYS@PROD>select trim(checkpoint_change#) from v$datafile;

 

TRIM(CHECKPOINT_CHANGE#)

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

717642

717642

717642

717642

717642

717642

717642

717642

717642

 

9 rows selected.

 

n  查询Start SCN也发生了变化,变成了前面Datafile Checkpoint SCN里变化的表空间的SCN

 

SYS@PROD>select trim(checkpoint_change#) from v$datafile_header;

 

TRIM(CHECKPOINT_CHANGE#)

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

717642

717642

717642

717642

717642

717642

717642

717642

717642

 

9 rows selected.

 

实验证明,发起Checkpoint是可以让System Checkpoint SCN、Datafile Checkpoint SCN、Start SCN变为redolog的High SCN的。但是切换日志是不能实现这个效果的。

 

4.        心跳

在Oracle中有一个事件叫Heartbeat,这个词在很多地方被提及,并且有着不同的含义(比如RAC中),我们这里要讨论的是CKPT的Heartbeat机制。Oracle通过CKPT进程每3秒将Heartbeat写入控制文件,以减少故障时的恢复时间。

-- 暂时没有理解

5.        数据库正常关闭启动

数据库正常关闭时,系统会执行一个完全检查点动作,并用该检查点时的SCN号更新上述4个SCN号,这时所有数据文件的Stop SCN会设置为数据文件头(v$datafile_header)的那个Start SCN(除了离线和只读的数据文件)。

 

数据库重新启动时,Oracle将数据文件头中的Start SCN与Datafile Checkpoint SCN比较,如果这两个值匹配,Oracle接下来再比较Datafile Checkpoint SCN和控制文件中Stop SCN,如果这个值也匹配,就意味着所有数据块已经提交,因此数据库不需要进行恢复,此时数据库直接打开。当所有的数据文件都打开之后,在线且可读写的数据文件终止SCN再次被设置为NULL,表示数据文件已经打开并能够正常使用了。有些表空间是只读的,这时控制文件中的System Checkpoint SCN号会不断增长,而Datfile Checkpoint SCN号和文件头中的Start SCN会停止更新直到表空间又设置为可读写,显然这时系统检查点SCN号会大于数据文件SCN和文件头启动SCN。

--可以理解

6.        数据库非正常关闭

数据库非正常关闭(或称为实例崩溃)时,Stop SCN不会被设置,依然为NULL,这可以通过把数据库启动至mount状态查询出来。这样重新启动时,SMON进程会执行实例恢复工作,即先执行前滚,再把数据库打开,最后执行回滚操作。

--可以理解

 

7.        数据文件介质故障

结果是:出现介质故障时,Datafile SCN及System Checkpoint SCN比文件头Start SCN大。

判断依据是:系统发生介质故障时,数据文件被以前的备份代替,控制文件中的Datafile Checkpoint SCN及System Checkpoint SCN肯定比被备份文件替换的数据文件的文件头中的Start SCN要大,这样Oracle就知道要对这个文件进行介质恢复。

--可以理解

 

8.        控制文件介质故障

结果是:System Checkpoint SCN及Datafile Checkpoint SCN比数据文件头Start SCN小。

 

判断依据是:在数据库恢复时,控制文件可能不是最新的,即把一个较早的控制文件还原为当前的控制文件,然后再执行恢复操作,这时控制文件中的System Checkpoint SCN和Datafile Checkpoint SCN可能比文件头的Start SCN小。这时恢复数据库要用下面命令:recover database using Backup Controlfile或其他的恢复语句。

--可以理解

 

9.        备份时的实例崩溃

当执行begin backup时实例崩溃:控制文件中的Datafile Checkpoint SCN和数据文件头Start SCN号相同,但是每个可读写的在线数据文件之间检查点SCN号不同,那么要求介质恢复,例如发出begin backup命令后就会出现这种情况,需要通过end backup命令才可以打开数据库

--可以理解

 

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

请登录后发表评论 登录
全部评论

注册时间:2015-09-21

  • 博文量
    211
  • 访问量
    276550