天天看點

oracle學習筆記 系統改變号(SCN)詳解oracle學習筆記 系統改變号(SCN)詳解

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)
------------------------ ---------------------------------------------------------------------------
                   -APR-  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;  

     CPDRT Low RBA              On disk RBA          CPODS            CPODT                     CPHBT
---------- -------------------- -------------------- ---------------- -------------------- ----------
                                           // ::   
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        

 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

就一個

查詢語句

結果:

SQL> select checkpoint_change# from v$database;

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

2)檔案scn

查詢語句

查詢結果:

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

NAME                                               CHECKPOINT_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應該有幾個

針對每個資料檔案都有一個scn号

3)結束scn

資料庫正常打開期間結束scn應該是null

查詢語句

查詢結果:

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号

查詢語句

查詢結果:

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

NAME                                               CHECKPOINT_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在資料檔案頭部的

5)日志檔案頭部的SCN

再看一個scn,

在日志檔案頭部。

資料庫執行個體有控制檔案、資料檔案、還有redolog,

redolog裡面記錄着日志。

日志是按照資料庫塊按照buffer改變的時間排列的。

現在的日志每一個條目都有scn号,

它按照時間排起來。

每一個日志檔案redolog日志檔案,

檔案頭有兩個scn,

一個叫first,

一個叫next,

每一個日志檔案檔案的頭部有一個first scn和next 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
           

現在有三組日志,

序列号為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                  
/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是551607,

這個資料就代表着這些資料檔案的新舊程度。

再看日志檔案的current狀态的redolog的FIRST_CHANGE#是551607,

就是current日志目前正在使用的日志的first。

大體可以知道資料庫突然崩了,

崩了以後這些控制檔案資料檔案它們的scn号是551607。

這個時候它們大體上需要551607以後的日志去恢複,

而551607的日志在current裡面,在最新的裡面,

我們恢複的時候隻需要current檔案就可以了,

另外兩個redolog不需要。

五)實驗改變SCN

1)

現在做一個操作

強行把日志切換一下

切換兩次:

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                  
/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,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                  
/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仍然是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#
------------------
            

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

NAME                                               CHECKPOINT_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,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                  
/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 * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
                                           NO  ACTIVE                   -APR-
                                           NO  CURRENT                  -APR-
                                           NO  INACTIVE                 -APR-
           

發現控制檔案中的系統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)

這時我們做這麼一個操作

将所有的髒塊全部寫回磁盤。

這時再查一下日志:

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#
------------------
            

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

NAME                                               CHECKPOINT_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>
SQL> select name,checkpoint_change# from v$datafile_header;

NAME                                               CHECKPOINT_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,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語句

可以知道:

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寫的頻率,

是以這個參數不要亂設。

設這個參數方法:

執行設定:

SQL> alter system set fast_start_mttr_target=;

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日

文字:韻筝