Oracle 中的 SCN(system change number)和我们的北京时间的意义是相同的,SCN 是 Oracle 中的
时间号。
为什么 Oracle 不用时间来界定呢?
我在北京时间 8:00 的时候执行一条 DML 语句,然后修改机器上的时间为 7:00,再执行一条 DML 语
句。如果用机器上的时间区分的话,那 Oracle 根本区分不出来这两条 DML 语句的执行顺序——而这一点
对于 Oracle 是很重要的。所以它采用自己产生的 SCN 来区分所有操作的先后顺序。
SCN 设计的值很大,所以不用担心达到最大值后怎么办。
可以查看系统当前的 SCN 号:
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
464640326
也可以查看系统当前保存的 SCN 号:
SQL> select checkpoint_change# from v$database
CHECKPOINT_CHANGE#
------------------
464639929
如果此时数据库损坏,当重启时候需要修复的,就是这两个 SCN 之间的数据。这些数据保存在在线重做日
志文件中:
SQL> select GROUP#, STATUS, FIRST_CHANGE# from v$log;
GROUP# STATUS FIRST_CHANGE#
---------- ------------------------------ -------------
1 INACTIVE 464633029
2 INACTIVE 464637664
3 CURRENT 464638303
group1 中保存的数据产生的 SCN 号为 464633029 至 464637664;group2 中的 SCN 号为
464637664 至 464638303;group3 中的 SCN 号为 464638303 至 464640326(当前 SCN号)。
所以,若此时执行 shutdown abort 并重启,执行 crash recovery 时,使用的在线重做日志文件为 group3
中的 member。而通过 v$log.status 字段也能看到:group3 的状态为 current。
源文地址:http://blog.chinaunix.net/u/30637/showart.php?id=524979
Part I. 透析 SCN 号
SCN 是当 Oracle 数据库更新后,由 DBMS 自动维护去累积递增的一个数字。当一笔交易 commit 时,
LGWR 会将 log buffer 写入 redo log file,同时也会将该笔交易的 SCN 同步写入到 redo log file内
(wait-until-completed)。因此当你 commit transaction 时,在交易成功的讯息返回之前,LGWR必
须先完整的完成上述行为之后,否则你是看不到提交成功的回应讯息。
可以查询目前系统最新的 SCN
SQL>select dbms_flashback.get_system_change_number from dual;
可以理解,这里返回的 SCN,也是目前redo log file 最新的 SCN 纪录。因为 commit 后的交易才会有 SCN,
而一旦 commit 就会立刻写入 redo log file 中。
CHECKPOINT 和 SCN 的关联
Checkpoint 发生的目的就是要把存储在 buffer 内的已提交交易写回 disk,否则一旦发生 crash,需要进
行 recovery 时,就必须花很多时间从 redo log file 内最后的 SCN 交易开始进行 recovery,这样在商业应
用上是很浪费时间和没有效率的。
当 commit 一笔交易时,只会立刻将 redo buffer 写入 redo log file 内,但是并不会马上将该 update 后
的 block(dirty block)同步写回 disk datafile 中,这是为了减少过多 disk IO,所以采取 batch方式写
入。
When a checkpoint occurs. Oracle must update the headers of alldatafiles to record the details
of the checkpoint. This is done by the CKPT process. The CKPT process does not write blocks to
disk; DBWn always performs that work.
在 shutdown normal or shutdown immediate 下,也就是所谓的 clean shutdown, checkpoint 也会
自动触发。当发生 checkpoint 时,会把 SCN 写到四个地方去。三个地方在 control file 内,一个在 datafile
header。
Control file 三个地方为:
1、 System checkpoint SCN
SQL> select to_char(checkpoint_change#, 'XXXXXXXXXXXX') from v$database;
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-----------------------------------------------------------------
7161D7365DC
2、 Datafile checkpoint SCN
SQL> select name, to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$datafile where name
like '%gisdts01%';
NAME
-------------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7365DC
3、 Stop SCN
SQL> select name,last_change# fromv$datafile where name like '%gisdts01%';
NAME
--------------------------------
/gisdata/datafile/gisdts01.dbf
正常 datafile 在 read-write mode 运作下,last_change#一定是 null
还有一个 SCN 在 datafile header 内
4、 Start SCN
SQL>select name,to_char(checkpoint_change#,'XXXXXXXXXXXX') fromv$datafile_header
where name like '%gisdts01%';
NAME
---------------------------------------------------------------TO_CHAR(CHECKPOINT_CHANGE#,'XX
---------------------------------------------------------------/gisdata/datafile/gisdts01.dbf
7161D7365DC
为什么储存在 control file 中要分为两个地方(system checkpoint scn, datafile checkpoint scn?)。
当把一个 tbs 设为 read-only 时,他的 scn 会冻结停止,此时 datafile checkpoint scn 是不会再递增改
变的,但是整体的 system checkpoint scn 却仍然会不断递增前进。所以这是为什么需要分别在两个地方
储存 SCN。
正常 shutdown database 后,SCN 会发生什么变化?
可以把数据库开在 mount mode
SQL> select to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$database;
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------
7161D7455B9
SQL>select name,to_char(checkpoint_change#,’XXXXXXXXXXXX’),to_char(last_change#
,’XXXXXXXXXXXX’) from v$datafile where name like '%gisdts01%';
NAME
-------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------
TO_CHAR(LAST_CHANGE#,'XXXXXXXX
-------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7455B9
7161D7455B9
可以看到储存在 control file 中的三个 SCN 的数值都是相同的,注意此时的 stop scn 不会是 null,而是
等于 start scn。
再来查询 datafile header 中的 SCN:
SQL> select name, to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$datafile_hea
der where name like '%gisdts01%';
NAME
-------------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7455B9
当 clean shutdown 时,checkpoint 会进行,并且此时 datafile 的 stop scn 和 start scn 会相同。等我
们打开数据库时,oracle 会检查 datafile header 中的 start scn 和存于 control file 中的 datafile 的 scn
是否相同,如果相同,接着检查 start scn 和 stop scn 是否相同,如果仍然相同,数据库会正常启动,否
则就需要 recovery….等到数据库 open 后,储存在 control file 中的 stop scn 就会恢复为 null 值,此时
表示 datafile 是 open 在正常模式下。
如果不正常 shutdown(shutdown abort),则 mount 数据库后,会发现 stop scn 并不等于其它位置的
scn,而是等于 null。这表示 oracle 在 shutdown 时没有进行 checkpoint,下次启动必须进行 crash
recovery。
原文地址 http://blog.chinaunix.net/u/12476/showart.php?id=142021
Part II. Oracle SCN 机制解析
SCN(System Chang Number)作为 oracle 中的一个重要机制,在数据恢复、Data Guard、Streams
复制、RAC 节点间的同步等各个功能中起着重要作用。理解 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 中的脏数据写入到数据文件中。
经过上述 5 个步骤,事务中的数据变化最终被写入到数据文件中。但是,一旦在上述中间环节时,数据
库意外宕机了,在重新启动时如何知道哪些数据已经写入数据文件、哪些没有写呢(同样,在 DG、streams
中也存在类似疑问:redo log 中哪些是上一次同步已经复制过的数据、哪些没有)?SCN 机制就能比较完
善的解决上述问题。
SCN 是一个数字,确切的说是一个只会增加、不会减少的数字。正是它这种只会增加的特性确保了
Oracle 知道哪些应该被恢复、哪些应该被复制。
总共有 4 中 SCN:系统检查点(System Checkpoint)SCN、数据文件检查点(Datafile Checkpoint)
SCN、结束 SCN(Stop SCN)、开始 SCN(Start SCN)。其中其面 3 中 SCN 存在于控制文件中,最
后一种则存在于数据文件的文件头中。
在控制文件中,System Checkpoint SCN 是针对整个数据库全局的,因而之存在一个,而 Datafile
Checkpoint SCN 和 Stop SCN 是针对每个数据文件的,因而一个数据文件就对应在控制文件中存在一份
Datafile Checkpoint SCN 和 StopSCN。在数据库正常运行期间,Stop SCN(通过视图 v$datafile 的字
段 last_change#可以查询)是一个无穷大的数字或者说是 NULL。
在一个事务提交后(上述第四个步骤),会在 redo log 中存在一条 redo 记录,同时,系统为其提供一
个最新的 SCN(通过函数 dbms_flashback.get_system_change_number 可以知道当前的最新 SCN) ,
记录在该条记录中。如果该条记录是在 redo log 被清空(日志满做切换时或发生 checkpoint 时,所有变
化日志已经被写入数据文件中),则其 SCN 被记录为 redo log 的 low SCN。以后在日志再次被清空前写
入的 redo 记录中 SCN 则成为 Next SCN。
当日志切换或发生 checkpoint(上述第五个步骤)时,从 Low SCN 到 Next SCN 之间的所有 redo
记录的数据就被 DBWn 进程写入数据文件中,而 CKPT 进程则将所有数据文件(无论 redo log 中的数据
是否影响到该数据文件)的文件头上记录的 Start SCN(通过视图 v$datafile_header 的字段
checkpoint_change#可以查询)更新为 Next SCN,同时将控制文件中的 System Checkpoint SCN(通
过视图 v$database 的字段 checkpoint_change#可以查询)、每个数据文件对应的 Datafile Checkpoint
(通过视图 v$datafile 的字段 checkpoint_change#可以查询)也更新为 Next SCN。但是,如果该数据
文件所在的表空间被设置为 read-only 时,数据文件的 Start SCN 和控制文件中 Datafile Checkpoint
SCN 都不会被更新。
那系统是如何产生一个最新的 SCN 的?实际上,这个数字是由当时的 timestamp 转换过来的。每当
需要产生一个最新的 SCN 到 redo 记录时,系统获取当时的 timestamp,将其转换为数字作为 SCN。我
们可以通过函数 SCN_TO_TIMESTAMP(10g 以后)将其转换回 timestamp:
SQL> select dbms_flashback.get_system_change_number,
SCN_TO_TIMESTAMP(dbms_flashback
.get_system_change_number) from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
SCN_TO_TIMESTAMP(DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER)
---------------------------------------------------------------------------
2877076756
17-AUG-07 02.15.26.000000000 PM
也可以用函数timestamp_to_scn将一个 timestamp 转换为 SCN:
SQL> select timestamp_to_scn(SYSTIMESTAMP) as scn from dual;
SCN
----------
2877078439
最后,SCN 除了作为反映事务数据变化并保持同步外,它还起到系统的“心跳”作用——每隔 3 秒左
右系统会刷新一次系统 SCN。
下面,在简单介绍一下 SCN 如何在数据库恢复中起作用。
数据库在正常关闭(shutdown immediate/normal)时,会先做一次 checkpoint,将 log file 中的
数据写入数据文件中,将控制文件、数据文件中的 SCN(包括控制文件中的 Stop SCN)都更新为最新的
SCN。
数据库异常/意外关闭不会或者只更新部分 Stop SCN。
当数据库启动时,Oracle 先检查控制文件中的每个 Datafile Checkpoint SCN 和数据文件中的 Start
SCN 是否相同,再检查每个 Datafile Checkpoint SCN 和 Stop SCN 是否相同。如果发现有不同,就从
Redo Log 中找到丢失的 SCN,重新写入数据文件中进行恢复。具体的数据恢复过程这里就不再赘述。
SCN 作为 Oracle 中的一个重要机制,在多个重要功能中起着“控制器”的作用。了解 SCN 的产生和
实现方式,帮助 DBA 理解和处理恢复、DG、Streams 复制的问题。
最后提一句,利用 SCN 机制,在 Oracle10g、11g 中又增加了一些很实用的功能——数据库闪回、数
据库负载重现等。
原文地址 http://www.hellodba.com/Doc/Oracle_SCN.htm
Part III. scn(系统改变号)信息与恢复
control 中有三种 SCN 分别为,system SCN、datafile SCN、last SCN,数据文件头中有一种 SCNstart
SCN
system scn 从视图 v$database 中获得,对应 checkpoint_change#字段,datafile scn、last scn 分别
对应视图 v$datafile 中的 checkpoint_change#,last_change#,而 start scn 则从 v$datafile_header
中 checkpoint_change#得到。
数据库在正常启动后下,system scn,datafile scn,start scn 会相等,而 last scn 会被置于无穷大,这里
为 null。
正常关闭后(immediate,noraml,translate),上面四个 scn 会应执行 full checkpoint 而相等。
当系统在非正常关闭后,如 shutdown abort,这个时候 last scn 依然为无穷大,那么当重新启动实例时,
系统首先会比较 start scn 与 system scn,如果一致,那么再比较 start scn 与 last scan 是否一样大,
因为是非正常关闭,这里会不一样大,那么就需要例程恢复。
如果打开数据库时发现 system scn>datafile scn,那么以为着使用旧的备份数据文件,也就是需要介质
恢复
如果是 system scn backup controlfile 进行恢复。
1、正常启动时
SQL> select checkpoint_change# from v$database; --控制文件中的 scn
CHECKPOINT_CHANGE#
------------------
5534071
SQL> select file#,checkpoint_change# from v$datafile_header; --start scn
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 5534071
2 5534071
3 5534071
4 5534071
5 5534071
SQL> select file#,checkpoint_change#,last_change# from v$datafile; --datafile scn & last scn
FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
1 5534071
2 5534071
3 5534071
4 5534071
5 5534071
2、正常关闭后,然后在 startup mount;
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 319888364 bytes
Fixed Size 453612 bytes
Variable Size 192937984 bytes
Database Buffers 125829120 bytes
Redo Buffers 667648 bytes
数据库装载完毕。
SQL> select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 5534485
2 5534485
3 5534485
4 5534485
5 5534485
SQL> select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
------------------
5534485
SQL> select file#,checkpoint_change#,last_change# from v$datafile;
FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
1 5534485 5534485
2 5534485 5534485
3 5534485 5534485
4 5534485 5534485
5 5534485 5534485
--发现 start scn=last scn,证明系统是正常关闭
SQL> alter database open;
数据库已更改。
3、在正常打开状态下进行事务操作
SQL> create table t(a number);
表已创建。
SQL> insert into t values (1);
已创建 1 行。
SQL> commit;
提交完成。
SQL> insert into t values(2);
已创建 1 行。
4、非正常关闭
SQL> shutdown abort;
ORACLE 例程已经关闭。
SQL>
5、打开到 mount 状态下,观看 scn
SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 319888364 bytes
Fixed Size 453612 bytes
Variable Size 192937984 bytes
Database Buffers 125829120 bytes
Redo Buffers 667648 bytes
数据库装载完毕。
SQL> select file#,checkpoint_change#,last_change# from v$datafile;
FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
1 5534486
2 5534486
3 5534486
4 5534486
5 5534486
SQL> select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
------------------
5534486
SQL> select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 5534486
2 5534486
3 5534486
4 5534486
5 5534486
--这时发现 start scn 与 last scn 不等,last scn 为无穷大,需要例程恢复
6、改变数据库状态为 open,并查看该阶段运行日志
SQL> select * from wen.t;
select * from wen.t
*
ERROR 位于第 1 行:
ORA-01219: 数据库未打开: 仅允许在固定表/视图中查询
SQL> alter database open;
数据库已更改。
SQL> select * from wen.t;
A
----------
1
--发现没有提交的事务丢失。
查看日志如下:
Completed: ALTER DATABASE MOUNT
Wed May 17 21:35:46 2006
alter database open
Wed May 17 21:35:46 2006
Beginning crash recovery of 1 threads --会自动判断是否需要恢复,这里开始例程恢复
Wed May 17 21:35:46 2006
Started first pass scan
Wed May 17 21:35:47 2006
Completed first pass scan
206 redo blocks read, 90 data blocks need recovery
Wed May 17 21:35:47 2006
Started recovery at
Thread 1: logseq 167, block 271, scn 0.0
Recovery of Online Redo Log: Thread 1 Group 2 Seq 167 Reading mem 0 --恢复用的在线重做日志
Mem# 0 errs 0: D:ORACLEORADATADB1REDO02.LOG
Wed May 17 21:35:47 2006
Ended recovery at
Thread 1: logseq 167, block 477, scn 0.5554724
90 data blocks read, 90 data blocks written, 206 redo blocks read
Crash recovery completed successfully --恢复完成
Wed May 17 21:35:47 2006
LGWR: Primary database is in CLUSTER CONSISTENT mode
Thread 1 advanced to log sequence 168
Thread 1 opened at log sequence 168
Current log# 3 seq# 168 mem# 0: D:ORACLEORADATADB1REDO03.LOG
Successful open of redo thread 1.
Wed May 17 21:35:48 2006
SMON: enabling cache recovery
Wed May 17 21:35:48 2006
ARC0: Evaluating archive log2 thread 1 sequence 167
ARC0: Beginning to archive log 2 thread 1 sequence 167
Creating archive destination LOG_ARCHIVE_DEST_1: 'D:DBBKARC00167.001'
ARC0: Completed archiving log 2 thread 1 sequence 167
Wed May 17 21:35:48 2006
Undo Segment 1 Onlined
Undo Segment 2 Onlined
Undo Segment 3 Onlined
Undo Segment 4 Onlined
Undo Segment 5 Onlined
Undo Segment 6 Onlined
原文地址 http://digifish.bokee.com/viewdiary.18440035.html
Part IV. 关于 SCN 的理解
1.oracle 正常运行时,control 文件的 SCN 是个很大的数,与 redo log 文件、数据文件的 SCN 不同,正
常关闭时,做完 checkpoint 后,三者的 SCN 值相同;
Biti:日志文件中 scn 有起始和结束 2 个(高低),在 current log 中高 scn 同样为无穷大。
2.当一个事务 commit 成功时,redo log文件中的 SCN+1,当该事务所做的修改写入数据文件后,数据文
件的 SCN+1;
Biti:commit 的时候加 1,其他很多时候也会加 1,只要数据库发生了变化都会增加。数据写入数据文件时
scn 不是加 1 而是由 ckpt 更新,检查点发生的时候才修改数据文件头的检查点计数并更新 scn。
3.疑问:
是不是如果一个事务比较大,在事务提交前就发生 redo log entries、data buffer 的写入,此时断电,则
数据文件、redo log 文件的 SCN 没有+1,且相同,但控制文件 SCN 不同,数据库 startup 时发生回滚。
Biti:数据文件是由 ckpt 进程更新文件头的,scn 不是加 1,而是更新为检查点发生那时的 scn,回滚是根
据回滚段头的事务表状态来进行的。
4.数据写入数据文件 scn 不是加 1 而是 ckpt 更新,检查点发生的时候才修改数据文件头的 检查点计数和
更新 scn
是不是应该这么说?:
当 ckpt 更新时发生数据写入,同时修改数据文件头的 检查点计数和更新 scn 。当出现其他情况下的数据
写入时(如无空闲缓冲等),不发生 ckpt ,但 SCN 会增加。
Biti:这个时候修改的是数据块但不是数据文件头,只有检查点发生的时候才更新数据文件头,也就是说只
有 ckpt 进程更新数据文件头(oracle8 以前如果没有 ckpt 进程就是 lgwr 更新),dbwr 只写数据块。
BTW:看样 DBWR 只是些数据块,只有 CKPT 进程才能更新数据文件头;
5.commit 的时候加一,其他很多时候也会加 1,只要数据库发生了变化都会增加。
很多时候,能否举一些例子
Biti: dml 一发生即使没有提交也会增加 scn, job 进程一样产生 scn,只要对数据库中文件发生任何的改变
都有可能产生 scn,SCN: system change number, not system commit number .也就是系统发生变化
时所产生的一个时间点
标志。不是提交的标志,只是因为提交也是系统的变化之一而已。
6.Biti:检查点的发生,跟写日志文件是没有必然联系的
检查点通知 DBWR 写数据文件,写完后 ckpt 更新控制文件头和数据文件头。
当 DBWR 写数据块的时候若发现数据块的相关 RDBA (位于日志文件的位置) 的 log block 还没有被写
入日志文件,则在 dbwr 写块之前必须通知 lgwr 把 log buffer 中日志写入日志文件。
7.data block 里面的 SCN 是当 block 被更改的时候的 SCN
而数据文件有那么多 block,自然不同的 block 有不同的 SCN
block 中存在 block SCN 和 ITL 中的 commit SCN
block SCN 又在块头和块尾都有,若不一致意味着 block 损坏(热备可能出现这个情况,需要从 redo log
中拷贝回来,若是正在修改的过程中由于进程死掉则 pmon 负责清理。若 由于一些以外发生这样的不一
致的情况,则查询的时候出现 1578 错误,当然该错误号也可能是物理磁盘损坏,这里表示逻辑的损坏!)
这个头和尾的 SCN 的检查时机跟这两个参数有关:
db_block_checking boolean FALSE
db_block_checksum boolean FALSE
该 2 参数信息请查阅 http://tahiti.oracle.com
而 ITL 中的 commit SCN 则跟 consistent gets and delay block cleanout 有关
数据文件头的 SCN 是检查点发生时更新的
代表着 当 恢复的时候从这个 SCN 点 开始在 log file 中寻找 redo 开始做恢复
8.According to Rama Velpuri's book, CKPT updates controlfiles, not their headers. It makes
sense because if you look at a controlfile dump, the header doesn't even have an SCN. But the
file body has sections for each datafile, and therefore each ofthem has an SCN to be updated.
It's odd that most books and also documentation don't even say CKPT updates controlfiles.
Follow-up to bellsz's original message. In controlfiles, the stop SCN is not a very big number; it's
in fact set to infinity when the database is open. Also, SCNs are incremented for many reasons,
mostly due to recursive transactions. Read Steve Adams and Hemant Chitale's answers at
http://groups.google.com/groups?sel...t_nospam.com.sg
9.
系统检查点 scn(v$database(checkpoint_change#))
数据文件检查点(v$datafile(checkpoint_change#))
数据文件终止 scn(v$datafile(last_change#))
数据文件中存放的检查点
启动 scn (v$datafile_header(checkpoint_change#)
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.
5>在数据库运行期间的 scn 值
在数据库打开并运行之后,控制文件中的系统检查点、控制文件中的数据文件检查点 scn
和每个数据文件头中的启动 scn 都是相同的。控制文件中的每个数据文件的终止 scn 都为 null.
在安全关闭数据库的过程中,系统会执行一个检查点动作,这时所有数据文件的终止 scn
都会设置成数据文件头中的那个启动 scn 的值。在数据库重新启动的时候,
Oracle 将文件头中的那个启动 scn 与数据库文件检查点 scn 进行比较,
如果这两个值相互匹配,oracle 接下来还要比较数据文件头中的启动 scn 和控制文件
中数据文件的终止 scn。如果这两个值也一致,就意味着所有数据块多已经提交,所有
对数据库的修改都没有在关闭数据库的过程中丢失,因此这次启动数据库的过程
也不需要任何恢复操作,此时数据库就可以打开了。当所有的数据库都打开之后,
存储在控制文件中的数据文件终止 scn 的值再次被更改为 null,
这表示数据文件已经打开并能够正常使用了。
10.
找了一些网页,发现 SCN 确实不只在事务提交时增加,以下是网页上的摘要:
1)
SCN means "System Change Number" not "System Commit Number".
However, because the SCN is always incremented at commits and seldom otherwise, it is OK to
use the two terms interchangeably.
2)
The SCN is incremented whenever a transaction commits. However,this is not the only source of
increments. In a seemingly idle database, the SCN gets incremented also through AQ, SMON,
job queues...
1 中说了 oracle seldom 操作也会引起 SCN 的增加,2 中更明确说了 AQ, SMON, job queues... 会导致
SCN 的增加,因此应该得出结论,在 ORACLE 中除了 COMMIT 会导致 SCN 增加外还有其它的 ORACLE
后台进程会导致 SCN 增加.
但是,是否是普通的DML 导致了SCN 的增加,还是由于DML 操作过程中后台进程导致了SCN 增加的假象?
请大家踊跃讨论!
还有 ORACLE 后台进程在何时,何种情况下导致了 SCN 增加,也请大家踊跃讨论!
Biti:这句话我应该更准确第表达一下
如果一个 dml 导致产生事务,则会产生一个 scn。这个意思是说
如果一个事务包含多个 dml,则只有第一个初始产生事务的 dml 产生 scn,提交的时候又是一个 scn
如果一个事务只有一个 dml,拿看起来就是 dml 产生一个 scn,提交或者回滚产生一个 scn
这是经过实验测试过的,如果你又兴趣,不紧紧是要找资料看,还可以动手证明。
你可以理解为 begin transaction and commit tansaction
至于没有 dml 的 commit ,那不叫一个 transaction
你不做任何 dml 而发出 rollback 命令 将会发现 v$sysstat 中 user rollbacks 将会增加 而
transactions 不会增加
所以你可以把结论定义为 事务的开始 和事务的结束都会导致 SCN 的增加,其他如 AQ/JOB 等也会产
生 SCN ……
同一个 block 上在一个事务中连续发生 255 个 DML 后 scn 也会增加
……
11.sys@DBAP01> select max(ktuxescnw*power(2,32)+ktuxescnb) from x$ktuxe;
MAX(KTUXESCNW*POWER(2,32)+KTUX
------------------------------
52211024
已用时间: 00: 00: 00.00
sys@DBAP01> alter system checkpoint;
系统已更改。
已用时间: 00: 00: 00.06
sys@DBAP01> select CHECKPOINT_CHANGE# from v$database;
CHECKPOINT_CHANGE#
------------------
52211055
已用时间: 00: 00: 00.00
sys@DBAP01> select max(ktuxescnw*power(2,32)+ktuxescnb) from x$ktuxe;
MAX(KTUXESCNW*POWER(2,32)+KTUX
------------------------------
52211053
x$ktuxe 计算出来的是已经结束的最新的事务的commit scn ,所以可小于当前系统scn。 检查点scn 自
然也小于当前系统 scn。 但是 检查点 scn 和 x$ktuxe 计算出来的大小却倚赖于 系统状况了。
current scn 是 系统当前所产生的最大 scn ,可能是当前未结束事务所产生的 scn。 在 9i 的
dbms_flashback.get_system_change_number 可以得到这个值,这个值应该是大于等于 x$ktuxe SCN
(这个 view 记录的是 当前数据库结束事务的最大 scn)