天天看點

關于oracle執行個體恢複的前滾和復原的了解

關于oracle執行個體恢複的一些了解,一直都有誤區,今天通過檢視相關資料和與同學探讨,發覺了自己的錯誤,探讨結果如下:

執行個體恢複:當資料庫非正常關閉的時候(斷電或者shu  abort等等非一緻性關閉),當你從新啟動資料庫的時候,資料庫相關程序自動進行執行個體恢複,無須人工幹預。

什麼時候需要執行個體恢複

在shutdown normal or shutdown immediate下,也就是所謂的clean shutdown,checkpoint也會自動觸發,并且把SCN紀錄寫回。 當發生checkpoint時,會把SCN寫到四個地方:

三個地方于control file内:

SYSTEM CHECKPOINT SCN

Datafile checkpoint SCN 

Stop SCN:就是在執行個體一緻性關閉的時候,更新

一個在datafile header内:

Start SCN

正常open的狀态下一緻性的資料庫,SYSTEM CHECKPOINT SCN,Datafile checkpoint SCN和資料檔案頭Start SCN的這三個SCN是一緻,并且儲存在control file中的stop scn就會恢複為NULL值。

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在正常模式下了。

非正常shutdown

如果不正常SHUTDOWN (shutdown abort),則mount資料庫後,會發現stop scn并不是等于其它位置的scn, 而是等于NULL,這表示Oracle在shutdown時沒有進行checkpoint,下次開機必須進行crash recovery(執行個體恢複)。

注意一點:

啟動資料庫時,如果發現STOP SCN = NULL,表示需要進行crash recovery;

啟動資料庫時,如果發現有datafile header的START SCN 不等于儲存于CONTROLFILE的DATAFILE SCN,表示需要進行Media recovery

執行個體恢複的具體過程

當資料庫突然崩潰,而還沒有來得及将buffer cache裡的髒資料塊重新整理到資料檔案裡,同時在執行個體崩潰時正在運作着的事務被突然中斷,則事務為中間狀态,也就是既沒有送出也沒有復原。這時資料檔案裡的内容不能展現執行個體崩潰時的狀态。這樣關閉的資料庫是不一緻的。

下次啟動執行個體時,Oracle會由SMON程序自動進行執行個體恢複。執行個體啟動時,SMON程序會去檢查控制檔案中所記錄的、每個線上的、可讀寫的資料檔案的END SCN号。

資料庫正常運作過程中,該END SCN号始終為NULL,而當資料庫正常關閉時,會進行完全檢查點,并将檢查點SCN号更新該字段,是以可以通過END SCN号是否為null來判斷是不是需要執行個體恢複。

而崩潰時,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表空間在内。

總   結

今天最重要的一點我知道了,所謂的前滾,是應用redo來恢複buffer cache的資料,将buffer cache恢複到crash之前狀态,是以此時buffer cache 中既有崩潰時已經送出還沒有寫入資料檔案的髒資料塊,也還有事務被突然終止,而導緻的既沒有送出又沒有復原的事務所弄髒的資料塊(也就是沒有commit,但是dbwr已經将改變重新整理到底層磁盤),還有一點是控制檔案中還有一個 end scn,用來記錄資料庫正常關閉的時候的資料庫檔案頭的scn,并且可以通過這個scn是否為null來判斷需或者不需執行個體恢複。

本文轉自 wangergui 51CTO部落格,原文連結:http://blog.51cto.com/wangergui/1932114,如需轉載請自行聯系原作者