一. 什麼時候需要執行個體恢複
在shutdown normal or shutdown immediate下,也就是所謂的clean shutdown,checkpoint也會自動觸發,並且把SCN紀錄寫回。 當發生checkpoint時,會把SCN寫到四個地方:
三個地方於control file內:
(1)SYSTEM CHECKPOINT SCN
(2)Datafile checkpoint SCN
(3)Stop SCN
一個在datafile header內:
Start SCN
1.1 Clean shutdown 時
當clean shutdown 時,checkpoint會進行,並且此時datafile的stop scn和控制檔案裡的start scn會相同。 等到open資料庫時,Oracle檢查datafile header中的start scn和存於control file中的datafile的scn是否相同, 如果相同,接著檢查start scn和stop scn是否相同,如果仍然相同,資料庫就會正常開啟,否則就需要recovery。
等到資料庫開啟後,儲存在control file中的stop scn就會恢複為NULL值,此時表示datafile是open在正常模式下了。
1.2 非正常shutdown
如果不正常SHUTDOWN (shutdown abort),則mount資料庫後,會發現stop scn並不是等於其它位置的scn, 而是等於NULL,這表示Oracle在shutdown時沒有進行checkpoint,下次開機必須進行crash recovery(執行個體恢複)。
注意一點:
(1)啟動資料庫時,如果發現STOP SCN = NULL,表示需要進行crash recovery;
(2)啟動資料庫時,如果發現有datafile header的START SCN 不等於儲存於CONTROLFILE的DATAFILE SCN,表示需要進行Media recovery
1.3 crash recovery 順序問題
必須先進行roll forward(從redo log file中從目前的start SCN開始,重做後面的已提交之交易)。 再從roll back segment 做rollback未完成(dead transaction)交易。檢驗controlfile中的SCN會等於datafile header的SCN
二. Crash Recovery 過程
當資料庫突然崩潰,而還沒有來得及將buffer cache裡的髒資料區塊重新整理到資料檔案裡,同時在執行個體崩潰時正在運行著的事務被突然中斷,則事務為中間狀態,也就是既沒有提交也沒有復原。這時資料檔案裡的內容不能體現執行個體崩潰時的狀態。這樣關閉的資料庫是不一致的。
下次啟動執行個體時,Oracle會由SMON進程自動進行執行個體恢複。執行個體啟動時,SMON進程會去檢查控制檔案中所記錄的、每個線上的、可讀寫的資料檔案的END SCN號。
資料庫正常運行過程中,該END SCN號始終為NULL,而當資料庫正常關閉時,會進行完全檢查點,並將檢查點SCN號更新該欄位。
而崩潰時,Oracle還來不及更新該欄位,則該欄位仍然為NULL。當SMON進程發現該欄位為空白時,就知道執行個體在上次沒有正常關閉,於是由SMON進程就開始進行執行個體恢複了。
SMON進程進行執行個體恢複時,會從控制檔案中獲得檢查點位置。於是,SMON進程到聯機記錄檔中,找到該檢查點位置,然後從該檢查點位置開始往下,應用所有的重做條目,從而在buffer cache裡又恢複了執行個體崩潰那個時間點的狀態。這個過程叫做前滾,前滾完畢以後,buffer cache裡既有崩潰時已經提交還沒有寫入資料檔案的髒資料區塊,也還有事務被突然終止,而導致的既沒有提交又沒有復原的事務所弄髒的資料區塊。
前滾一旦完畢,SMON進程立即開啟資料庫。但是,這時的資料庫中還含有那些中間狀態的、既沒有提交又沒有復原的髒塊,這種髒塊是不能存在於資料庫中的,因為它們並沒有被提交,必須被復原。開啟資料庫以後,SMON進程會在後台進行復原。
有時,資料庫開啟以後,SMON進程還沒來得及復原這些中間狀態的資料區塊時,就有使用者進程發出讀取這些資料區塊的請求。這時,伺服器處理序在將這些塊返回給使用者之前,由伺服器處理序負責進行復原,復原完畢後,將資料區塊的內容返回給使用者。
三. 為什麼資料庫的執行個體恢複是先前滾再復原
復原段實際上也是以復原資料表空間的形式存在的,既然是資料表空間,那麼肯定就有對應的資料檔案,同時在buffer cache 中就會存在映像塊,這一點和其他資料表空間的資料檔案相同。
當發生DML操作時,既要產生REDO(針對DML操作本身的REDO Entry)也要產生UNDO(用於復原該DML操作,記錄在UNDO資料表空間中),但是既然UNDO資訊也是使用復原資料表空間來存放的,那麼該DML操作對應的UNDO資訊(在BUFFER CACHE產生對應中的UNDO BLOCK)就會首先產生其對應的REDO資訊(UNDO BLOCK's REDO Entry)並寫入Log Buffer中。
這樣做的原因是因為Buffer Cache中的有關UNDO資料表空間的塊也可能因為資料庫故障而丟失,為了保障在下一次啟動時能夠順利進行復原,首先就必須使用REDO日誌來恢複UNDO段(實際上是先回複Buffer Cache中的髒資料區塊,然後由Checkpoint寫入UNDO段中),在資料庫OPEN以後再使用UNDO資訊來進行復原,達到一致性的目的。
產生完UNDO BLOCK's REDO Entry後才輪到該DML語句對應的REDO Entry,最後再修改Buffer Cache中的Block,該Block同時變為髒資料區塊。
實際上,簡單點說REDO的作用就是記錄所有的資料庫更改,包括UNDO資料表空間在內。