shifo0409
作者shifo0409·2019-06-13 09:36
信息分析/架构师·日本ITS会社

Oracle数据库中的SCN(system change number)详解

字数 7505阅读 5406评论 1赞 3

通俗的理解

Oracle中的SCN(system change number)相当于数据库中的一个时钟,只不过不是用时分秒来计量,这种内部时钟机制,可称为逻辑时钟,每个数据库都有一个全局SCN生成器,本质上就是不重复的数字。

为什么Oracle不用系统时间来计录呢?原因是机器上的时间容易被人为修改,从而易造成内部记录的错乱。所以它采用自己产生的SCN来区分所有操作的先后顺序。

SCN号具体概述

SCN是当Oracle数据库更新后,由DBMS自动维护去累积递增的一个数字。Oracle数据库中一共有4种SCN分别为

系统检查点SCN: 系统检查点SCN位于控制文件中,当检查点进程启动时(ckpt),Oracle就把系统检查点的SCN存储到控制文件中。该SCN是全局范围的,当发生文件级别的SCN时,例如将表空间置于只读状态,则不会更新系统检查点SCN。

查询系统检查点SCN的命令如下

SQL> select CHECKPOINT_CHANGE# from v$database;

CHECKPOINT_CHANGE

590694

数据文件scn:当ckpt进程启动时,包括全局范围的(比如日志切换)以及文件级别的检查点(将表空间置为只读、begin backup或将某个数据文件设置为offline等),这时会在控制文件中记录的scn。

查询数据文件SCN的命令如下

SQL> alter tablespace users read only;
Tablespace altered.

SQL> select file#,checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#


1 592277
2 592277
3 592277
4 592291
5 592277

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE

592277

可以看到4号文件也就是users表空间所属的文件scn值和其他文件不一致,且比系统检查点的scn要大。

结束scn:每个数据文件都有一个结束scn,在数据库的正常运行中,只要数据文件在线且是可读写的,结束scn为null。否则则存在具体的scn值。结束scn也记录在控制文件中。

SQL>select TABLESPACE_NAME,STATUS from dba_tablespaces
TABLESPACE_NAME STATUS


SYSTEM ONLINE
UNDOTBS1 ONLINE
SYSAUX ONLINE
TEMP ONLINE
USERS READ ONLY
EXAMPLE ONLINE

SQL> select file#,LAST_CHANGE# from v$datafile;
FILE# LAST_CHANGE#


1
2
3
4 592291
5

可以看到除了users表空间的结束scn不为空,其他数据文件的结束scn为空。

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

SQL> shutdown immediate;
SQL> startup mount;

SQL> select file#,last_change# from v$datafile;
FILE# LAST_CHANGE#


1 592608
2 592608
3 592608
4 592291
5 592608

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

查询数据文件头SCN的命令如下

SQL> select file#,CHECKPOINT_CHANGE# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#


1 592608
2 592608
3 592608
4 592291
5 592608

SCN的机制

数据库运行时的SCN

我们先看下oracle事务中的数据变化是如何写入数据文件的:

1、 事务开始;

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

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

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

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

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。

SQL> select recid,sequence#,first_change#,next_change# from v$log_history ;
RECID SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#


1 1 446075 474154
2 2 474154 497385
3 3 497385 516087
4 4 516087 540659
5 5 540659 564897
6 6 564897 564903
7 7 564903 565320
8 8 565320 565704
9 9 565704 565715
10 10 565715 567343
11 11 567343 587705

查看currnet redolog中的high scn

SQL>select vf.member,v.status,v.first_change# from v$logfile vf,v$log v
2 where vf.group#=v.group#
3* and v.status='CURRENT'

MEMBER STATUS FIRST_CHANGE#


/u01/app/oradata/orcl/redo02.log CURRENT 587705

SQL>alter system dump logfile ' /u01/app/oradata/orcl/redo02.log';

SQL> show parameter user_dump
NAME TYPE VALUE


user_dump_dest string /home/oracle/admin/c001/udump

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

DUMP OF REDO FROM FILE '/u01/app/oradata/orcl/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 = 169869568=0xa200100
Db ID=1269936864=0x4bb1b2e0, Db Name='ORCL'
Activation ID=1269912032=0x4bb151e0
Control Seq=696=0x2b8, File size=102400=0x19000
File Number=2, Blksiz=512, File Type=2 LOG

descrip:"Thread 0001, Seq# 0000000012, SCN 0x00000008f7b9-0xffffffffffff"
thread: 1 nab: 0x34f6 seq: 0x0000000c hws: 0x9 eot: 1 dis: 0
resetlogs count: 0x2c3c676f 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.0008f7b9 (587705) 04/20/2011 09:35:56
Next scn: 0xffff.ffffffff 01/01/1988 00:00:00
Enabled scn: 0x0000.0006ce7b (446075) 02/03/2011 18:29:03
Thread closed scn: 0x0000.00090ae0 (592608) 04/20/2011 15:29:05
Disk cksum: 0x30ee Calc cksum: 0x30ee
Terminal recovery stop scn: 0x0000.00000000
Terminal recovery 01/01/1988 00:00:00
Most recent redo scn: 0x0000.00000000
Largest LWN: 1920 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值可通过如下命令查看

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

594373

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

日志切换或者checkpoint

当日志切换或发生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都不会被更新。

心跳

在Oracle中有一个事件叫Heartbeat,这个词在很多地方被提及,并且有着不同的含义(比如RAC中),我们这里要讨论的是CKPT的Heartbeat机制。

Oracle通过CKPT进程每3秒将Heartbeat写入控制文件,以减少故障时的恢复时间。

数据库正常关闭启动

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

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

数据库非正常关闭

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

数据文件介质故障

出现介质故障时,数据文件检查点SCN及系统检查点SCN比文件头启动SCN大。系统发生介质故障时,数据文件被以前的备份代替,控制文件中的数据文件检查点SCN肯定比文件头中的启动SCN要大,这样Oracle就知道要对这个文件进行介质 恢复

控制文件介质故障

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

备份时的实例崩溃

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

SCN号的补充内容:

SCN号记录到日志文件,控制文件,数据文件及许多数据库表记录。

一、查看数据库的当前SCN号

SQL> select dbms_flashback.get_system_change_number from dual;
SQL> select current_scn from v$database;

二、SCN存储于在线重做日志文件中

SQL> select GROUP#, STATUS, FIRST_CHANGE# from v$log;

GROUP# STATUS FIRST_CHANGE#


1 INACTIVE 464633029
2 INACTIVE 464637664
3 CURRENT 464638303

三、SCN存在于控制文件中

补充:
控制文件中的信息包括:
1.数据库的名字,取自初始化参数说明的数据库名字或CREATE DATABASE语句中所使用的名字
2.数据库创建时间戳,是数据库创建时产生的。
3.数据库标识符,是创建数据库时ORACLE自动生成的。
4.联机重做日志文件的名字和准确位置,增加删除修改重做日志文件时,ORACLE会修改相关信息。
5.当前日志的序列号,是在日志切换时ORACLE记录的。
6.检查点信息CHECKPOINT,是在产生校验点时ORACLE记录的以及SCN。
7.日志的历史信息,是在日志切换时ORACLE记录的。
8.归档日志文件的准确位置和状态,是在重做日志文件被归档(复制到归档日志文件)时ORACLE记录的
9,数据文件的名字和准确位置,增加删除修改数据文件名字,ORACLE会修改相关信息。
10.表空间的相关信息,增加删除表空间时,ORACLE会修改相关信息。
11.备份准确位置和状态,这些信息是由恢复管理器记录的。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

3

添加新评论1 条评论

wuwenpinwuwenpin软件开发工程师南京
2019-06-14 08:48
感谢分享!
Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广