SCN: System Change Number
SCN是順序遞增的一個數字,在Oracle 中用來標識數據庫的每一次改動,及其先後順序。SCN的最大值是0xffff.ffffffff。
Oracle對SCN的管理
單節點的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文件中。
幾種重要的SCN
Commit SCN
當用戶提交commit命令後,系統將當前scn賦給該transaction。這些信息都反映在redo buffer中,並馬上更新到redo log 文件裏。
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方式打開時,該表空間就無法再改回在線狀態。
Checkpoint SCN
當數據庫內存的髒數據塊(dirty blocks)寫到各數據文件中時,就發生一次checkpoint。數據庫的當前checkpoint scn值存在x$kccdi.discn中。Checkpoint scn在數據庫恢復中起着至關重要的作用。無論你用何種辦法恢復數據庫,只有當各個數據庫文件的checkpoint scn都相同時,數據庫才能打開。
雖然參數“_allow_resetlogs_corruption”可以在checkpoint scn不一致時強制打開數據庫,但是這樣的數據庫在open後必須馬上作全庫的export,然後重建數據庫並import數據。
Resetlog SCN
數據庫不完全恢復時,在指定時間點後的scn都無法再應用到數據庫中。Resetlog時的scn就被設成當前數據庫scn,redo log也會被重新設置。
Stop SCN
Stop scn記錄在數據文件頭上。當數據庫處在打開狀態時,stop scn被設成最大值0xffff.ffffffff。在數據庫正常關閉過程中,stop scn被設置成當前系統的最大scn值。在數據庫打開過程中,Oracle會比較各文件的stop scn和checkpoint 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
關於如何使用參數_allow_resetlogs_corruption,可參見文檔http://www.sidibe.net/allow_resetlog.html