oracle学习笔记 系统改变号(SCN)详解

2 篇文章 0 订阅
2 篇文章 0 订阅

oracle学习笔记 系统改变号(SCN)详解

这节课讲一下oracle里面的另外一个概念SCN,在以后的学习中经常的会碰到。

一)SCN是什么

SCN翻译成英文是:system change number。

可以这么告诉你在oracle的边边角角里面时时刻刻在用到SCN,
所以说SCN是我们以后经常面对的一个概念。

首先来讲我们看到的scn是个数字,是一串数字。
是由一个时间经过一个函数算过来的,
同样的它经过一个函数把scn转换成一个时间。
也就是scn其实就是一个时间。

系统用scn号而不用时间,
是因为在这里时间和时间之间经常要去比较。
对计算机来讲两个时间进行比较,
它首先比较秒再比较分再比较小时再比较年月日,
它比较很麻烦。
在计算机里面两个时间的比较其实就是两个字符串的比较,
比较起来很麻烦而且记录起来也不方便。

但是对计算机来讲你让它比较两个数字很容易。
因为计算机它就是计算数字的,
所以说在计算机内部,
它更喜欢用数字去比较而不是用时间去比较。

记得我们在讲sharedpool的时候,
比较两个sql语句一不一样,
我们把sql语句进行hash以后哈希运算以后得到一个数字,
另外一个sql语句经过哈希以后也得到一个数字,
两个数字如果不相等的话,
两个sql语句肯定不相等。
所以说计算机特别的喜欢用数字来表示一些东西,
我们的scn号也一样。

我们的时间,
说白了主要用来:
第一比较先后,昨天是3号今天是4号,时间可以让我们比较先后。
再一个是比较新旧。
在oracle数据库里面oracle为了保证数据的一致性,
在很多地方都用到scn号。

在一个地方填一个scn号,
目的就标志着这个数据或者这个点或者这个日志的一个新旧还有先后,
所以说scn号说白了就是一个时间点。

我给一条日志后面加上scn号,
其实就是给这个日志加上时间点,
加上时间点的目的就是标志着这个日志的一个先后。

我们先看一个sql语句

select dbms_flashback.get_system_change_number, 
SCN_TO_TIMESTAMP(dbms_flashback.get_system_change_number) from dual;

执行结果:

SQL> select dbms_flashback.get_system_change_number,
SCN_TO_TIMESTAMP(dbms_flashback.get_system_change_number) from dual;  2

GET_SYSTEM_CHANGE_NUMBER SCN_TO_TIMESTAMP(DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER)
------------------------ ---------------------------------------------------------------------------
                  544160 21-APR-17 06.50.25.000000000 AM

544160是SCN号 。
21-APR-17 06.50.25.000000000 AM是当前的时间。
他们是对应的,
通过SCN号可以推出时间来,
通过时间可以推出SCN号来。

SCN号就是时间,
SCN号的目的就是比较先后比较新旧的,在后面会真正体会到。

二)oracle中有哪些SCN

在oracle数据库里面 有些地方都用到了SCN号。
首先来讲,
控制文件中有几个地方用到SCN号:
第一叫系统SCN;
第二叫文件SCN;
第三叫结束SCN。
这是控制文件中的最经典的三个SCN号。

上节课讲过,
增量检查点发生CKPT进程会
将检查点队列的第一个数据块的所对应的LRBA地址记录到控制文件中,
同时它还会将这个时候对应的时间点,
把CKPT发生的时间点给记录到控制文件中。

上节课用到的sql语句:

SQL> select CPDRT,CPLRBA_SEQ||'.'||CPLRBA_BNO||'.'||CPLRBA_BOF "Low RBA",
CPODR_SEQ||'.'||CPODR_BNO||'.'||CPODR_BOF "On disk RBA",CPODS,CPODT,CPHBT from x$kcccp;  2

     CPDRT Low RBA              On disk RBA          CPODS            CPODT                     CPHBT
---------- -------------------- -------------------- ---------------- -------------------- ----------
       104 5.84220.0            5.86914.0            548629           04/21/2017 07:02:59   911690073
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0

8 rows selected.

CPDRT是脏块的数量。

我们知道如果这个时间点数据库突然崩了的话,
oralce在做实例恢复的时候,
会从LRBA跑到On disk RBA,
终点是current日志的最后一条日志。

current日志的最后一条日志在那里记着是On disk RBA,
开始位置是LRBA,
这段就是它要跑的日志。

CPODS是SCN号,
这个SCN记录的不是检查点发生的时间scn,
是on disk rba这条日志所对应的scn号。
这个scn号可能对我们理解的意义不是很大,但实际很有用。

增量检查点并不会去更新数据文件头,以及控制文件中数据库SCN以及数据文件条目的SCN信息,
而只是每3秒由CKPT进程去更新控制文件中的low cache rba信息,也就是检查点的位置。

我们重点看,
系统SCN、文件SCN、结束SCN,
控制文件中的这三个SCN号。

数据库中有控制文件,
假设系统有四个数据文件有四个dbf文件。

在控制文件中有一个系统SCN号。

同时控制文件中针对每一个数据文件,
还有一个文件SCN号 ,
每个数据文件对应控制文件中的一个文件SCN号。

针对这四个文件,
每个数据文件对应控制文件中的一个结束SCN号。

在每个数据文件的头部,
还有一个开始SCN号start SCN号。

它们的意义:
为了保证数据文件的一致性,
为了保证文件的一致性。

三)SCN在恢复中作用

正常的情况下数据库打开以后,
系统scn、在控制文件中的对四个数据文件记录的文件scn,
以及数据文件头部的起始scn,
它们应该相等的。

1)结束SCN是空

控制文件中的结束scn,
因为数据库打开了文件都打开了还没有结束,
这四个scn应该是空也可以叫做无穷大是空,
数据库正常运行期间应该是这样的。

数据库正常关闭以后,
oracle会把buffercache里所有的缓存写到磁盘上,
同时更新系统scn、控制文件中的文件scn和数据文件头的开始scn。
用关闭的时间点去更新。
同时将终止scn设置成和
系统scn、文件scn、文件头开始scn一样,
因为终止了,终止的点有了。

数据库正常关闭以后,
系统、文件、结束 和 start scn这一串scn都是一样的。
数据库正常打开正常使用和正常关闭,
它们都是一样的。

如果数据库非正常关闭,
比如数据库运行期间数据库突然崩了!

这个时候系统的终止scn是空,
控制文件中对四个文件记录的终止scn是空的,
因为它非正常关闭没有把终止scn给同步到和别的scn一样。

所以数据库下次启动的时候,
就会发现终止scn是空。
oracle就知道数据库非正常关闭,
非正常关闭就需要恢复,
需要恢复的时候oracle发现,
系统scn文件scn开始scn它们都是一样的,
唯独终止scn是空。
这时oracle就认为需要做实例恢复。

oracle做实例恢复的时候,
需要的是redolog,实例恢复不需要归档log,
而且只需要redolog的部分日志不是所有。

oracle发现需要做实例恢复的时候,
需要跑日志。
在控制文件中记录着lrba和on disk rba,
oracle就找这段日志,
而这段日志在redolog里面。

redolog有三种状态,
inactive、active和current。

oracle找一段日志,
比如从active到current,
然后跑日志。
跑日志完了以后实例恢复就就结束了,
数据库打开了,打开接着运行了。

oracle通过这几个scn来判断是否需要实例恢复,
这些scn说白了就是一个作用,
就是保证我oracle数据的一致性。

2)一个数据文件是旧文件

我们再看另外一种状况!

数据库关闭了,
关闭以后把第一个文件给它删除了换成一个旧的备份文件过来,
把以前备份过的这个文件换过来。

oracle启动的时候就会发现,
这个文件的头部的起始scn和控制文件中记录的scn不一样,
不一样的时候oracle就需要使用日志去跑成一样。

在行业里面经常说的一句话,
叫跑日志,跑日志的目的是提升scn。

我这个数据文件换个旧的过来这个scn偏低,
scn偏低说明这个文件相对别的文件来讲是旧了,
文件旧我就要跑日志,
跑日志最终目的是把scn跑成新的,
实际是跑日志是将数据文件的曾经的改变再重现一次。

这就是这四个scn关联起来的一些作用。
我们知道这个scn的作用以后,
就可以对我们以后的备份恢复非常有帮助。

什么时候需要做什么事情就分析scn号。

四)查看SCN

我们分别去查一下这几个scn

1)系统scn

就一个

查询语句

select checkpoint_change# from v$database;

结果:

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
            525838

2)文件scn

查询语句

select name,checkpoint_change# from v$datafile;

查询结果:

SQL> select name,checkpoint_change# from v$datafile;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  525838
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 525838
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  525838
/u01/app/oracle/oradata/jiagulun/users01.dbf                   525838
/u01/app/oracle/oradata/jiagulun/example01.dbf                 525838

文件scn应该有几个
针对每个数据文件都有一个scn号

3)结束scn

数据库正常打开期间结束scn应该是null

查询语句

select name,last_change# from v$datafile;

查询结果:

SQL> select name,last_change# from v$datafile;

NAME                                               LAST_CHANGE#
-------------------------------------------------- ------------
/u01/app/oracle/oradata/jiagulun/system01.dbf
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf
/u01/app/oracle/oradata/jiagulun/users01.dbf
/u01/app/oracle/oradata/jiagulun/example01.dbf

上面这三个scn号都在控制文件中

4)数据文件的头部scn号

查询语句

select name,checkpoint_change# from v$datafile_header;

查询结果:

SQL> select name,checkpoint_change# from v$datafile_header;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 551607
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/users01.dbf                   551607
/u01/app/oracle/oradata/jiagulun/example01.dbf                 551607

这个不在控制文件中
这个scn在数据文件头部的

5)日志文件头部的SCN

再看一个scn,
在日志文件头部。

数据库实例有控制文件、数据文件、还有redolog,
redolog里面记录着日志。

日志是按照数据库块按照buffer改变的时间排列的。

现在的日志每一个条目都有scn号,
它按照时间排起来。

每一个日志文件redolog日志文件,
文件头有两个scn,
一个叫first,
一个叫next,
每一个日志文件文件的头部有一个first scn和next scn。

我们可以执行一下语句看一下

select * from v$log;

执行结果

SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         1          1          5   52428800          1 NO  INACTIVE                525838 18-APR-17
         2          1          6   52428800          1 NO  CURRENT                 551607 21-APR-17
         3          1          4   52428800          1 NO  INACTIVE                510969 13-MAY-16

现在有三组日志,
序列号为SEQUENCE#列,
这里是5、6、4,
这个序列号唯一代表这个日志。

5号日志的FIRST_CHANGE#是525838这是first,
下一个日志6号日志的first就是上一个日志的next,
也就是这个日志的next和下一个日志的first是相等的。
这里5号日志first是525838,next是551607。

scn号就是时间点 ,
也就是这个日志是哪个时间段记录的可以列出来可以找出来。

redolog中的first应该是这个日志文件的第一条日志的scn 号,
next就认为是最后一条,也就是下一个日志的第一条,也就是这个日志的最后一条。

first和next记录的是这个日志文件所有的日志条目的scn号的范围。

数据库正常运行期间,
有四个scn应该相等的 。
控制文件中有仨,数据文件头有一个,
控制文件中的两个应该和数据文件头的scn是相等的,另外一个应该是空。
日志文件里面的first和next是这个日志文件第一条日志和最后一条日志的日志范围。

6)当前数据库SCN的状况

SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         1          1          5   52428800          1 NO  INACTIVE                525838 18-APR-17
         2          1          6   52428800          1 NO  CURRENT                 551607 21-APR-17
         3          1          4   52428800          1 NO  INACTIVE                510969 13-MAY-16

当前SCN范围有了。

查一下数据文件的SCN:

SQL> select name,checkpoint_change# from v$datafile;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 551607
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/users01.dbf                   551607
/u01/app/oracle/oradata/jiagulun/example01.dbf                 551607

数据文件的和系统的它们应该都一样,
数据文件的SCN是551607,
这个数据就代表着这些数据文件的新旧程度。

再看日志文件的current状态的redolog的FIRST_CHANGE#是551607,
就是current日志当前正在使用的日志的first。

大体可以知道数据库突然崩了,
崩了以后这些控制文件数据文件它们的scn号是551607。
这个时候它们大体上需要551607以后的日志去恢复,
而551607的日志在current里面,在最新的里面,
我们恢复的时候只需要current文件就可以了,
另外两个redolog不需要。

五)实验改变SCN

1)

现在做一个操作

alter system switch logfile;

强行把日志切换一下

切换两次:

SQL> alter system switch logfile;

System altered.

SQL> alter system switch logfile;

System altered.

我们再去查系统当前的scn号:

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
            551607

还是原来的551607

查文件scn:

SQL> select name,checkpoint_change# from v$datafile;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 551607
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/users01.dbf                   551607
/u01/app/oracle/oradata/jiagulun/example01.dbf                 551607

文件结束scn:

SQL> select name,last_change# from v$datafile;

NAME                                               LAST_CHANGE#
-------------------------------------------------- ------------
/u01/app/oracle/oradata/jiagulun/system01.dbf
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf
/u01/app/oracle/oradata/jiagulun/users01.dbf
/u01/app/oracle/oradata/jiagulun/example01.dbf

查数据文件头的scn:

SQL> select name,checkpoint_change# from v$datafile_header;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 551607
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  551607
/u01/app/oracle/oradata/jiagulun/users01.dbf                   551607
/u01/app/oracle/oradata/jiagulun/example01.dbf                 551607

scn仍然是551607

再查日志的开始scn:

SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         1          1          8   52428800          1 NO  CURRENT                 559246 21-APR-17
         2          1          6   52428800          1 NO  INACTIVE                551607 21-APR-17
         3          1          7   52428800          1 NO  INACTIVE                559229 21-APR-17

序列为6的redolog开始scn仍然是551607,
但已不是current状态了,
最新的8号redolog的状态是current。

系统当前控制文件中的scn它的新旧程度是551607。
日志里面最旧的6号是551607,
7号日志是559229,
8号日志是559246。
如果这时候数据库突然崩了,
我需要从6号日志开始来恢复来实例恢复然后7号和8号,
8号current有最后一条日志,
需要三个日志文件。

所以说这些文件的scn号主要意义就是标示这个文件的新旧程度。

当做日志切换的时候做很多操作的时候,
系统scn号始终没有改变,
其实这四个scn号主要的作用是用来标志着这些文件的新旧程度和一致程度。
在控制文件中有具体的LRBA地址,
具体oracle恢复的时候oracle找lrba地址去跑日志。

2)

这时如果我们再做一次日志切换:

SQL> alter system switch logfile;

System altered.

仍然使用上面的命令查看scn号:

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
            559246

SQL> select name,checkpoint_change# from v$datafile;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  559246
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 559246
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  559246
/u01/app/oracle/oradata/jiagulun/users01.dbf                   559246
/u01/app/oracle/oradata/jiagulun/example01.dbf                 559246

SQL> select name,last_change# from v$datafile;

NAME                                               LAST_CHANGE#
-------------------------------------------------- ------------
/u01/app/oracle/oradata/jiagulun/system01.dbf
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf
/u01/app/oracle/oradata/jiagulun/users01.dbf
/u01/app/oracle/oradata/jiagulun/example01.dbf

SQL> select name,checkpoint_change# from v$datafile_header;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  559246
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 559246
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  559246
/u01/app/oracle/oradata/jiagulun/users01.dbf                   559246
/u01/app/oracle/oradata/jiagulun/example01.dbf                 559246

SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         1          1          8   52428800          1 NO  ACTIVE                  559246 21-APR-17
         2          1          9   52428800          1 NO  CURRENT                 560640 21-APR-17
         3          1          7   52428800          1 NO  INACTIVE                559229 21-APR-17

发现控制文件中的系统scn、文件scn和各数据文件头的scn号都变为了559246。
因为原来的scn号为551607的6号文件已经归档,
所以系统改变的控制文件的scn号为处于active状态的最早的那个日志的first scn。

3)

如果这时再做一次日志切换

结果

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
            560640

SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         1          1          8   52428800          1 NO  INACTIVE                559246 21-APR-17
         2          1          9   52428800          1 NO  ACTIVE                  560640 21-APR-17
         3          1         10   52428800          1 NO  CURRENT                 560989 21-APR-17

系统scn仍然是序号最低的active状态的first scn

4)

这时我们做这么一个操作

alter system flush buffer_cache

将所有的脏块全部写回磁盘。

这时再查一下日志:

SQL>  select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         1          1          8   52428800          1 NO  INACTIVE                559246 21-APR-17
         2          1          9   52428800          1 NO  INACTIVE                560640 21-APR-17
         3          1         10   52428800          1 NO  CURRENT                 560989 21-APR-17

除了current状态的日志外都是inactive状态的日志了。

active意思是表示这个日志文件中的日志所对应的脏缓冲区还没写回到磁盘上,
active表示这个日志不能被覆盖。
同时因为这个脏缓冲区还没写回去就意味着实例恢复的时候还需要active这个日志,
现在它们都inactive了。

我们去查一下系统的scn号:

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
            560989

SQL> select name,checkpoint_change# from v$datafile;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  560989
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 560989
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  560989
/u01/app/oracle/oradata/jiagulun/users01.dbf                   560989
/u01/app/oracle/oradata/jiagulun/example01.dbf                 560989

SQL>
SQL> select name,checkpoint_change# from v$datafile_header;

NAME                                               CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  560989
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 560989
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  560989
/u01/app/oracle/oradata/jiagulun/users01.dbf                   560989
/u01/app/oracle/oradata/jiagulun/example01.dbf                 560989

SQL> select name,last_change# from v$datafile;

NAME                                               LAST_CHANGE#
-------------------------------------------------- ------------
/u01/app/oracle/oradata/jiagulun/system01.dbf
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf
/u01/app/oracle/oradata/jiagulun/users01.dbf
/u01/app/oracle/oradata/jiagulun/example01.dbf

scn都是560989

日志里面:

SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         1          1          8   52428800          1 NO  INACTIVE                559246 21-APR-17
         2          1          9   52428800          1 NO  INACTIVE                560640 21-APR-17
         3          1         10   52428800          1 NO  CURRENT                 560989 21-APR-17

current的日志scn为569089。

数据文件头部的和控制文件中的几个scn号,
它们记录的是日志文件中的active或current状态的日志那个first scn号。

六)redolog状态和SCN的关系

在数据库实例,
buffercache中有很多脏缓存区,
logbuffer中有日志,
redolog中有日志。

一开始先用redolog中的一个最下面的日志,
logbuffer中的日志往redolog中的一个日志里写,
这些日志对应buffercache中的脏缓冲区。

一个redolog写满了,
redolog的first有了,它的next也有了。
但是因为它的日志对应的这些脏块还没有写到磁盘,
就意味着这个日志,
第一不能被覆盖,
第二将来作实例恢复的时候它还需要。
这个时候我的数据文件和系统scn号就等于它的first。

这个redolog写完以后切换到另一个redolog,
它有first了还没有next。
用这个redolog的时候也是一样写日志,
这个日志来自buffercache中的脏缓冲区。
这个redolog用完了F有了、N有了,
但是它还是active。
因为io因为DBWR一直没有把buffercache中的脏块写回磁盘。
这个redolog就是active,
上一个redolog也是active,
两个active,
另一个redolog成了current了。

两个active意味着这些数据文件将来要数据恢复的时候,
需要这三个redolog文件,
需要这两个active和一个current。

这时候那几个文件系统scn等于最老的active的first change。

然后dbwr往磁盘写以后最老的这个文件变成inactive了,
变成inactive意味着什么这个文件可以被覆盖了。

这个时候这些文件、系统包括起始scn也就是那三个scn,
就等于第二个redolog现在处于active状态的那个active的first change了。

七)跑日志的开始位置

系统、文件、起始scn,
这三个scn它等于redolog里面最老的那一个active的日志的firstchange。
将来根据这三个scn可以找到到底需要从哪个日志里跑日志。

当然了找到这个文件以后,
一个文件里面有一万行日志,
不是都跑,
控制文件中还有一个具体的lrba地址。

用scn定位第一个active文件,
在文件里面根据lrba地址再去跑日志。

这三个scn是定位用哪个redolog文件,
然后控制文件中lrba地址再确定文件中从哪个地址开始。

当检查点进程发生的时候,
它有没有更新系统和数据文件头部的scn那四个scn。
系统、文件、结束和起始有四个scn,
oracle的检查点进程发生的时候没有更新这四个scn号。
它只是更新了控制文件中的一个lrba地址。
结束scn只有数据库关闭的时候它才会更新,
另外的三个scn只有一个日志从active变成inactive的时候它才会更新,
因为它记录的是最老的active的日志的first change。

八)scn在几种恢复时的作用

将来备份恢复,
控制文件、数据文件、还有redolog一堆的scn,scn oracle是串联起来用的。

1)

数据库突然关了没有正常关闭。

stop scn是无穷大是空,
这时oracle知道要做实例恢复,
根据lrba地址去找相关的文件去跑日志。

2)

如果我把一个数据文件换成一个旧的,
oracle发现这个数据文件的头部和控制文件中记录的scn不一样,
这个时候跑日志的时候光redolog不行了还需要归档日志。

因为这个数据文件太旧了,
它需要的日志可能已经被覆盖了,
被覆盖以后就去了归档了,
可能需要归档和redolog合起来把它跑成新的。

3)

另外一个,
我把数据库关了,
把控制文件和四个数据文件全部都换成旧的了。

仅仅判断这四个scn不能发现数据库是新是旧,
还会去看redolog。
它发现redolog里面的日志的scn号比那四个scn所有的都新,
就知道你用旧的替换了也会需要做恢复。
这时仅仅凭这些日志redolog也不行,
因为可能换的太旧也需要归档。

scn号就这个意义,
scn号处处都有意义,
讲备份恢复的时候还会讲。

4)

一个用户,
把数据库关了把数据库全部备份了,
控制文件、数据文件、redolog全备了。

备出来以后数据库出问题了,
他把全部恢复回去了。
启动时数据库没有做任何恢复启动起来了。
这是因为你全部都恢复回来以后,
oralcle发现所有的scn和redolog中的scn都是一样的,
它就认为数据库都是新的,就打开了。
我这个恢复就是一个典型的错误!
还有一堆archivelog,oracle并不知道它确实不知道,
所以说就出现问题了。

它错误在不应该把redolog覆盖了。

scn号学熟了以后很多问题自然就分析出来了。

九)日志SCN的first和next

我们看一个sql语句

select recid,sequence#,first_change#,next_change# from v$log_history where rownum<6;

可以知道:

SQL> select recid,sequence#,first_change#,next_change# from v$log_history where rownum<6;

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
---------- ---------- ------------- ------------
         1          1        446075       475356
         2          2        475356       480656
         3          3        480656       510969
         4          4        510969       525838
         5          5        525838       551607

这是以往的一些日志的first 和 next,
这里只列出了前五个,因为有rownum<6的条件。
一条记录的next等于下一个记录的first,串起来的。

十)数据块的SCN

数据块的事务槽以及回滚段的事务表是以后要讲的一个重点知识,
先简单讲一下。

数据块里面有scn号,
日志也有scn号。

比如说oracle跑日志的时候,
就使用日志修改数据块。

假设这个块是新的,日志比较旧。
跑日志的时候,日志要修改这个数据块,
发现这个日志的scn号比这个数据块的scn号旧,
这个日志会略过去会空跑。

对oracle数据库做实例恢复或者说介质恢复的时候,
我跑日志可以多,多没关系别少了,
少了肯定有问题但可以多。

比如正规讲,
假设从一个地方开始跑日志,
但是oracle不太好确定到底从哪里开始跑,
它从较低的一个位置开始跑,
跑多了没关系,
因为日志即使跑了,
它不会因为跑两次或者多跑了而导致这个数据块被修改两次。

因为数据块有scn号日志有scn号,
旧的日志不可能对新的块产生作用,
跑日志跑多了没关系它会出现空跑,
记住日志不怕多。

跑日志会把数据块跑成新的把数据文件变成新的提升scn号。

回滚段以及事务槽也有scn号放到后面单独重点去讲。

十一)fast_start_mttr_target参数

oracle有一个参数:

fast_start_mttr_target。

MTTR:Mean Time To Recover 恢复的平均时间。

这个参数的意义是,如果发生实例恢复,为了达到快速启动,而设置的实例恢复所需的时间的目标。
系统会按这个参数去改变数据库LRBA和OnDiskRBA之间的日志数目,
使发生实例恢复时所用的时间尽量的接近这个参数所设的时间值。
可以采取的方法由oracle系统决定,如自动调整DBWr写脏块的频率。

这个参数我们尽量不要改它。

SQL> show parameter fast_start_mttr_target;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
fast_start_mttr_target               integer     0

这个参数默认值value是0,单位默认秒,
为0时让oracle自己去调节。

数据库启动的时候,
要实例恢复的时候oracle需要前滚日志,
前滚的时间取决于跑日志的长度。

跑日志长意味着需要恢复的脏块多,
你的dbwr写的慢,或者buffercache比较大dbwr写的慢。

这个时间fast_start_mttr_target它是秒。
如果是20,
这时候oralce会尽量的满足oracle做实例恢复的时候,
它的时间控制的前滚的时间控制在20秒以内。

控制时它会加大dbwr的写的频率。
如我把时间设成一秒,
这时候的oracle的数据库里面dbwr会频繁的写。
这样不见得好,
所以这个参数不要乱设。

对我们来讲,
可能数据库启动花了两分钟花了一分钟,
我们不是很在意,
花五分钟我们也不在意,
当然有的数据库在意有的数据库不在意,
大部分不会在意那么几分钟。
既然不在意的话这个参数不要设,
因为一旦设了以后,
会间接的影响dbwr写的频率,
所以这个参数不要乱设。

设这个参数方法:

alter system set fast_start_mttr_target=600;

执行设置:

SQL> alter system set fast_start_mttr_target=600;

System altered.

看一下这个参数:

SQL> show parameter fast_start_mttr_target;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
fast_start_mttr_target               integer     600

这时候数据库里面的dbwr写的频率就会发生改变。

dbwr写的很频繁就会出问题io会很繁忙,
进而势必会影响serverprocess这个进程的读的一个性能。

这就是scn号,一堆的scn,scn有什么意义。

十二)总结

关于检查点队列、检查点进程 以及scn的某些细节,
在各方面的资料说法都有些出入包括官方文档。
前面碰到过几次这种情况了!
原因是由于从oracle8以后的多次版本频繁的升级,每次升级对有些内容都有修改。
使用原理和实现方法在不断的变化,
对使用和理解造成了麻烦。

这个地方出现了一样的情况也找不到一个统一的答案,
本人觉得老师讲的有道理,这里就按老师讲课的内容为准了。

下面说一下总结的几个要点:

检查点发生时检查点队列进程CKPT可以触发DBWr进程写脏块,
但它只是触发DBWr的其中的一种情况,并且只是触发,触发后就不管了。
触发的DBWr进行完了,CKPT并没有对这次触发的回应。

CKPT每间隔3秒自动的向控制文件中写一次lrba。这个和触发DBWr没有关系,是独立进行的。

检查点队列这个技术其实就是来确定日志的起点。
文件的scn号主要意义就是标示这个文件的新旧程度。
scn说白了就是一个作用就是保证我oracle数据的一致性。

增量检查点并不会去更新数据文件头,以及控制文件中数据库SCN信息,
而只是每3秒由CKPT进程去更新控制文件中的low cache rba信息,也就是检查点的位置。
结束scn只有数据库关闭的时候它才会更新,
另外的三个scn只有一个日志从active变成inactive的时候它才会更新,
因为它记录的是最老的active和current的日志的first change。

当检查点发生时,如果日志进行了切换,可能间接的引起系统SCN的更新。

2017年5月5日
文字:韵筝

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值