SCN是當Oracle資料更新後,由DBMS自動維護去累積遞增的一個數字。 當一個交易commit時,LGWR會將log buffer寫入redo log file,同時也會將該筆交易的 SCN同步寫入到redo log file內(wait-until-completed)。因此當你commit transaction時, 在交易成功的訊息返回之前,LGWR必須先完整的完成上述行為之後,否則你是看不到提交成功的回應訊息。
我們可以查詢目前系統最新的SCN
select dbms_flashback.get_system_change_number from dual;
可以理解的,這裡返回的SCN,也是目前redo log file最新的SCN紀錄。 因為commit後的交易才會有SCN,而一旦commit就會立刻寫入redo log file中。
CHECKPOINT 和 SCN 的關連
checkpoint發生的目的就是要把儲存在buffer內的已提交交易寫回disk,否則一旦發生crash,需要 進行recovery時,你就必須花很多的時間從redo log file內最後的SCN交易開始進行recovery,這樣 在商業應用上是很浪費時間和沒有效率的。
重點在於當commit一個交易時,只會立刻將redo buffer寫入redo log file內,但是並不會馬上將 該update後的block(dirty block)同步寫回disk datafile中,這是為了減少過多disk IO的考量,所以採取batch的方式寫入。
When a checkpoint occurs, Oracle must update the headers of all datafiles to record the details of the checkpoint. This is done by the CKPT process. The CKPT process does not write blocks to disk; DBWn always performs that work.
在shutdown normal or shutdown immediate下,也就是所謂的clean shutdown,checkpoint也會自動觸發,並且把SCN紀錄寫回。 當發生checkpoint時,會把SCN寫到四個地方去。三個地方於control file內,一個在datafile header。
Control file三個地方為
1.System checkpoint SCN ===========> (SYSTEM CHECKPOINT SCN in control file)
SQL> select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
--------------------
292767
2.Datafile checkpoint SCN ===============> (DATAFILE CHECKPOINT SCN in control file)
SQL> select name,checkpoint_change#
from v$datafile where name like '%users01%';
NAME CHECKPOINT_CHANGE#
----------------------------------- --------------------
/u02/oradata/OMFD1/users01.dbf 292767
3.Stop SCN ======================> (STOP SCN in control file)
SQL> select name,last_change#
from v$datafile where name like '%users01%';
NAME LAST_CHANGE#
----------------------------------- ------------
/u02/oradata/OMFD1/users01.dbf
正常datafile在read-write mode運作下,Last_change#一定是NULL
另外一個地方在datafile header內
4.Start SCN ================================> (DATAFILE HEADER)
SQL> select name,checkpoint_change#
from v$datafile_header where name like '%users01%';
NAME CHECKPOINT_CHANGE#
----------------------------------- --------------------
/u02/oradata/OMFD1/users01.dbf 292767
為什麼儲存在CONTROL FILE中要分為兩個地方(SYSTEM CHECKPOINT SCN,DATAFILE CHECKPOINT SCN ?) 當你把一個tbs設為read-only時,他的SCN會凍結停止,此時DATAFILE CHECKPOINT SCN是不會再遞增改變的, 但是整體的SYSTEM CHECKPOINT SCN卻仍然會不斷遞增前進。
所以,這就是為什麼需要分別在兩個地方儲存SCN。
<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
正常shutdown database後,SCN會發生什麼變化?
我們可以把資料庫開在mount mode
select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
--------------------
293184
select name,checkpoint_change#,last_change# from v$datafile where name like '%user%';
NAME CHECKPOINT_CHANGE# LAST_CHANGE#
----------------------------------- -------------------- --------------
/u02/oradata/OMFD1/users01.dbf 293184 293184
可以看到儲存在control file中的三個SCN位置都是相同,注意此時的stop scn不會是NULL,而是等於start scn
我們也來查詢datafile header SCN:
select name,checkpoint_change# from v$datafile_header where name like '%users01%';
NAME CHECKPOINT_CHANGE#
----------------------------------- --------------------
/u02/oradata/OMFD1/users01.dbf 293184
當clean shutdown 時,checkpoint會進行,並且此時datafile的stop scn和start scn會相同。 等到我門開啟資料庫時,Oracle檢查datafile header中的start scn和存於control file中的datafile的scn是否相同, 如果相同,接著檢查start scn和stop scn是否相同,如果仍然相同,資料庫就會正常開啟,否則就需要recovery... 等到資料庫開啟後,儲存在control file中的stop scn就會恢復為NULL值,此時表示datafile是open在正常模式下了。
如果不正常SHUTDOWN (shutdown abort),則mount資料庫後,你會發現stop scn並不是等於其他位置的scn, 而是等於NULL,這表示Oracle在shutdown時沒有進行checkpoint,下次開機必須進行crash recovery。
crash recovery
必須先進行roll forward(從redo log file中從目前的start SCN開始,重做後面的已提交之交易)
再從roll back segment 做rollback未完成(dead transaction)交易
檢驗controlfile中的SCN會等於datafile header的SCN
select 'controlfile' "SCN location",name,checkpoint_change#
from v$datafile where name like '%users01%'
union
select 'file header',name,checkpoint_change#
from v$datafile_header where name like '%users01%';
SCN location NAME CHECKPOINT_CHANGE#
-------------- ----------------------------------- --------------------
controlfile /u02/oradata/OMFD1/users01.dbf 293188
file header /u02/oradata/OMFD1/users01.dbf 293188
crash recovery vs media recovery
啟 動資料庫時,如果發現STOP SCN = NULL,表示需要進行crash recovery;啟動資料庫時,如果發現有datafile header的START SCN 不等於儲存於CONTROLFILE的DATAFILE SCN,表示需要進行Media recovery
STOP SCN equal NULL ==> NEED CRASH RECOVERY
DATAFILE HEADER START SCN not equal CONTROLFILE SCN ==> NEED MEDIA RECOVERY
RECOVERY DATABASE 兩種常見問題
1) RECOVER DATABASE UNTIL CANCEL ==> OPEN DATABASE RESETLOG
==> DATAFILE HEADER SCN一定會小於CONTROLFILE的DATAFILE SCN
如果你有進行RESTORE DATAFILE,則該RESTORE的DATAFILE HEADER SCN一定會小於目前CONTROLFILE的DATAFILE SCN,此時會無法
開啟資料庫,必須進行media recovery~~重做archive log直到該datafile header的SCN=current scn
restore datafile後,可以mount database然後去檢查controlfile and datafile header的SCN
select 'controlfile' "SCN location",name,checkpoint_change#
from v$datafile where name like '%users01%'
union
select 'file header',name,checkpoint_change#
from v$datafile_header where name like '%users01%';
SCN location NAME CHECKPOINT_CHANGE#
-------------- ----------------------------------- --------------------
controlfile /u02/oradata/OMFD1/users01.dbf 313551
file header /u02/oradata/OMFD1/users01.dbf 313401
2) RECOVER DATABASE UNTIL CANCEL USING BACKUP CONTROLFILE; ===> OPEN DATABASE RESETLOG
==> DATAFILE HEADER SCN一定會大於CONTROLFILE的DATAFILE SCN
如果只是某TABLE被DROP掉,沒有破壞資料庫整體資料結構,還可以用INCOMPLETE RECOVERY解決 如果是某個TABLESPACE OR DATAFILE被DROP掉,因為檔案結構已經破壞,目前的CONTROL FILE內已經沒有 該DATAFILE的資訊,就算你只RESTORE DATAFILE然後進行INCOMPLETE RECOVERY也無法救回被DROP的DATA FILE。
只好RESOTRE 之前備份的CONTROL FILE(裡頭被DROP DATAFILE Metadata此時還存在),不過RESTOREC CONTROL FILE後 此時Oracle會發現CONTROL FILE內的SYSTEM SCN會小於目前的DATAFILE HEADER SCN,也不等於目前儲存於LOG FILE內的SCN, 此時就必須使用RECOVER DATABASE UNTIL CANCEL USING BACKUP CONTROLFILE到DROP DATAFILE OR DROP TABLESPACE之前的SCN。
另一種特殊狀況就是,萬一不幸地所有CONTROL FILE都遺失了,也必須用這種方式救回,所以請做MULTIPLEXING。