ORACLE SCN 深入解析

最近在學習備份恢復,發現SCN號在深入理解恢復還是很重要的,於是就整理了一下網上關於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中的髒數據寫入到數據文件中。


1.SCN概念(The  System Change  Number)
SCN可以理解爲一個邏輯時鐘來記錄數據庫事件,也就是一個順序遞增的數字。
SCN的最大值是0xffff.ffffffff。

2.SCN的管理方式
Oracle對SCN的管理,分爲單節點和RAC兩種方式。

單節點的instance中
單節點的instance中,SCN值存在SGA區,由system commit number latch保護。任何進程要得到當前的SCN值,都要先得到這個latch。

RAC/OPS環境中
Oracle通過排隊機制(Enqueue)實現SCN在各並行節點之間的順序增長。具體有兩種方法:
Lamport算法:又稱麪包房算法,先來先服務算法。跟很多銀行採用的排隊機制一樣。客戶到了銀行,先領取一個服務號。一旦某個窗口出現空閒,擁有最小服務號的客戶就可以去空閒窗口辦理業務。
Commit廣播算法:一有commit完成,最新的SCN就廣播到所有節點中。
上述兩種算法可以通過調整初始化參數max_commit_propagation_delay來切換。在多數系統(除了Compaq Tur64 Unix)中,該參數的默認值都是700釐秒(centisecond),採用Lamport算法。如果該值小於100釐秒,Oracle就採用廣播算法,並且記錄在alert.log文件中。

3.SCN號是怎麼產生的呢
實際上,這個數字是由當時的timestamp轉換過來的。每當需要產生一個最新的SCN到redo記錄時,系統獲取當時的timestamp,將其轉換爲數字作爲SCN。
我們可以通過函數SCN_TO_TIMESTAMP(10g以後)將其轉換回timestamp
SQL> select  dbms_flashback.get_system_change_number scn, scn_to_timestamp(dbms_flashback.get_system_change_number)  time   from  dual;

       SCN  TIME
----------  --------------------------------
   3056178  16-MAR-12 03.32.58.000000000 PM

也可以用函數timestamp_to_scn將一個timestamp轉換爲SCN:
SQL> select  timestamp_to_scn(sysdate)  from  dual;

TIMESTAMP_TO_SCN(SYSDATE)
-------------------------
                  3056200

4.幾種重要的SCN

Commit SCN
在一個事務提交後(上述第四個步驟),會在redo log中存在一條redo記錄,同時,系統爲其提供一個最新的SCN(通過函數dbms_flashback.get_system_change_number可以知道當前的最新SCN),記錄在該條記錄中。

High and Low SCN
Oracle的Redo log會順序紀錄數據庫的各個變化。一組redo log文件寫滿後,會自動切換到下一組redo log文件則上一組redo log的high scn就是下一組redo log的low scn
在視圖v$log_history中,sequence#代表redo log的序列號,first_change#表示當前redo log的low scn,列next_change#表示當前redo log的high scn。
SQL> col recid format 9999
SQL> col requence# format 9999
SQL> col first_change# format 9,999,999,999,999
SQL> col next_change# format 9,999,999,999,999
SQL> select recid,sequence#,first_change#,next_change# from v$log_history where rownum<6;
RECID SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
----- ---------- ------------------ ------------------
484 484 1,928,645,840,091
1,928,645,840,436
485 485 1,928,645,840,436 1,928,645,840,636
486 486 1,928,645,840,636 1,928,778,045,209
487 487 1,928,778,045,209 1,929,255,480,725
488 488 1,929,255,480,725 1,930,752,214,033


Offline SCN
除了System tablespace以外的任何表空間,當我們執行SQL>alter tablespace…offline normal命令時,就會觸發一個checkpoint,將內存中的dirty buffer寫入磁盤文件中。Checkpoint完成後,數據文件頭會更新checkpoint scn和offline normal scn值。其中數據庫文件頭的checkpoint scn值可通過查詢列x$kccfe.fecps得到。
如果執行SQL>alter tablespace…offline命令時採用temporary或immediate選項,而不用normal選項時,offline normal scn會被設成0。這樣當數據庫重啓後通過resetlog方式打開時,該表空間就無法再改回在線狀態。(resetlogs裏面還是有很多東西要學習和理解的)

Checkpoint SCN
與checkpoint相關的SCN號有四個,其中三個存在控制文件中,一個存放在數據文件頭中,下面在SCN於數據庫恢復的關係是 會有詳細的講解)

當數據庫內存的髒數據塊(dirty blocks)寫到各數據文件中時,就發生一次checkpoint。數據庫的當前checkpoint scn值存在x$kccdi.discn中。Checkpoint scn在數據庫恢復中起着至關重要的作用。無論你用何種辦法恢復數據庫,只有當各個數據庫文件的checkpoint scn都相同時,數據庫才能打開。

雖然參數“_allow_resetlogs_corruption”可以在checkpoint scn不一致時強制打開數據庫,但是這樣的數據庫在open後必須馬上作全庫的export,然後重建數據庫並import數據。


5.SCN號與oracle數據庫恢復的關係

SCN號與oracle數據庫恢復過程有着密切的關係,只有很好地理解了這層關係,才能深刻地理解恢復的原理,從而才能很好地解決這方面的問題。

SCN與CHECKPOINT

CKPT進程在checkpoint發生時,將當時的SCN號寫入所有非只讀數據文件頭無論redo log中的數據是否影響到該數據文件)同時將控制文件中的System Checkpoint SCN(通過視圖v$database的字段checkpoint_change#可以查詢)、每個數據文件對應的Datafile Checkpoint(通過視圖v$datafile的字段checkpoint_change#可以查詢),同時通知DBWR進程將數據塊寫到數據文件。

CKPT進程也會在控制文件中記錄RBA(redo byte address),以標誌Recovery需要從日誌中哪個地方開始。

與checkpoint相關的SCN號有四個,其中三個存在控制文件中,一個存放在數據文件頭中。
這四個分別是:
1.System Checkpoint SCN
當checkpoint完成後,ORACLE將System Checkpoint SCN號存放在控制文件中。我們可以通過下面SQL語句查詢:
select checkpoint_change# from v$database;
2.Datafile Checkpoint SCN
當checkpoint完成後,ORACLE將Datafile Checkpoint SCN號存放在控制文件中。我們可以通過下面SQL語句查詢所有數據文件的Datafile Checkpoinnt SCN號。
select name,checkpoint_change# from v$datafile;
3.Start SCN號
ORACLE將Start SCN號存放在數據文件頭中。
這個SCN用於檢查數據庫啓動過程是否需要做Media Recovery.
我們可以通過以下SQL語句查詢:
select name,checkpoint_change# from v$datafile_header;
4.End SCN (Stop SCN)號
ORACLE將End SCN號存放在控制文件中。
這個SCN號用於檢查數據庫啓動過程是否需要做Instance Recovery.
我們可以通過以下SQL語句查詢:
select name,last_change# from v$datafile;
在數據庫正常運行的情況下,對可讀寫的,online的數據文件,該SCN號爲NULL.

我們作個小的試驗,內容如下:
在執行檢查點進程之前SCN號如下:
System Checkpoint   scn:
SQL> select checkpoint_change#  from  v$database;


CHECKPOINT_CHANGE#
------------------
           3053495

Datafile Checkpoint   scn:

NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf                 3053495

/opt/app/oracle/oradata/orcl/undotbs01.dbf               3053495

/opt/app/oracle/oradata/orcl/sysaux01.dbf                 3053495
          
/opt/app/oracle/oradata/orcl/users01.dbf                   3053495
          
/home/oracle/dpump/part1.dbf                                    3031971

注:我們看到各個數據文件頭中記錄的start scn號都是相同的(但是/home/oracle/dpump/part1.dbf 卻跟其他不一樣,原因是這裏part.dbf  所在的表空間是隻讀的,數據文件的Start SCN和控制文件中Datafile Checkpoint SCN都不會被更新。)
          
Start SCN:
SQL> select name,checkpoint_change# from v$datafile_header;
NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf                 3053495

/opt/app/oracle/oradata/orcl/undotbs01.dbf               3053495

/opt/app/oracle/oradata/orcl/sysaux01.dbf                 3053495
          
/opt/app/oracle/oradata/orcl/users01.dbf                   3053495
          
/home/oracle/dpump/part1.dbf                                    3031971

End SCN:
SQL>select name,last_change# from v$datafile;
NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf               

/opt/app/oracle/oradata/orcl/undotbs01.dbf              

/opt/app/oracle/oradata/orcl/sysaux01.dbf                
          
/opt/app/oracle/oradata/orcl/users01.dbf                   
          
/home/oracle/dpump/part1.dbf                                    3031971

注:在數據庫正常運行的情況下,對可讀寫的,online的數據文件,該SCN號爲NULL. 對於只讀文件,stop scn號3031971 與 start scn號3031971,Datafile Checkpoint   scn3031971  是相同的,


執行alter system checkpoint。後的SCN號如下:
System Checkpoint SCN:
SQL> select checkpoint_change#  from  v$database;
CHECKPOINT_CHANGE#
------------------
           3055942
Datafile Checkpoint SCN :
SQL>select  name ,checkpoint_change#  from  v$datafile;
NAME                                                                         CHECKPOINT_CHANGE#
/opt/app/oracle/oradata/orcl/system01.dbf                    3055942
        
/opt/app/oracle/oradata/orcl/undotbs01.dbf                   3055942
       
/opt/app/oracle/oradata/orcl/sysaux01.dbf                    3055942
 
/opt/app/oracle/oradata/orcl/users01.dbf                      3055942
            
/home/oracle/dpump/part1.dbf                                       3031971
          
Start SCN:
SQL>select name,checkpoint_change# from v$datafile_header;
NAME                                                                         CHECKPOINT_CHANGE#
/opt/app/oracle/oradata/orcl/system01.dbf                    3055942
        
/opt/app/oracle/oradata/orcl/undotbs01.dbf                   3055942
       
/opt/app/oracle/oradata/orcl/sysaux01.dbf                    3055942
 
/opt/app/oracle/oradata/orcl/users01.dbf                      3055942
            
/home/oracle/dpump/part1.dbf                                       3031971

End SCN :
SQL>select name,last_change# from v$datafile;
NAME                                                                        CHECKPOINT_CHANGE#
------------------------------------------------------               ---------------------------------
/opt/app/oracle/oradata/orcl/system01.dbf               

/opt/app/oracle/oradata/orcl/undotbs01.dbf              

/opt/app/oracle/oradata/orcl/sysaux01.dbf                
          
/opt/app/oracle/oradata/orcl/users01.dbf                   
          
/home/oracle/dpump/part1.dbf                                    3031971
注:對只讀表空間,其數據文件的Datafile Checkpoint SCN、Start SCN和END SCN號均相同。
這三個SCN在表空間處於只讀期間都將被凍結。

SCN不連續原因可能如下: 
1.當發生日誌組切換的時候
2.當符合LOG_CHECKPOINT_TIMEOUT,LOG_CHECKPOINT_INTERVAL,fast_start_io_target,fast_start_mttr_target參數設置的時候
3.當運行ALTER SYSTEM SWITCH LOGFILE的時候
4.當運行ALTER SYSTEM CHECKPOINT的時候
5.當運行alter tablespace XXX begin backup,end backup的時候
6.當運行alter tablespace ,datafile offline的時候;

6.SCN號與數據庫啓動
第一步:在數據庫啓動過程中,檢查System Checkpoint SCN、Datafile Checkpoint SCN和Start SCN號都相同時,如果相同數據庫可以正常啓動,不需要做media recovery.三者當中有一個不同時,則需要做media recovery。
第二步:在不需要做media recovery情況下,若End SCN號爲NULL,則需要做instance recovery。

ORACLE在啓動過程中首先檢查是否需要media recovery,然後再檢查是否需要instance recovery。

7.SCN號與數據庫關閉

數據庫在正常關閉(shutdown immediate/normal)時,會先做一次checkpoint,將log file中的數據寫入數據文件中,將控制文件、數據文件中的SCN(包括控制文件中的Stop SCN)都更新爲最新的SCN。數據庫異常/意外關閉不會或者只更新部分Stop SCN。


在理解和學習resetlog的時候,SCN還是會用到的!!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章