關於oracle例項恢復的前滾和回滾的理解

賀子_DBA時代發表於2016-11-04
    關於oracle例項恢復的一些理解,一直都有誤區,今天透過檢視相關資料和與同學探討,發覺了自己的錯誤,探討結果如下:
      例項恢復:當資料庫非正常關閉的時候(斷電或者shu  abort等等非一致性關閉),當你從新啟動資料庫的時候,資料庫相關程式自動進行例項恢復,無須人工干預,
      一. 什麼時候需要例項恢復
    在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
 正常open的狀態下一致性的資料庫,SYSTEM CHECKPOINT SCN,Datafile checkpoint SCN和資料檔案頭Start SCN的這三個SCN是一致,並且儲存在control file中的stop scn就會恢復為NULL值,
1.1 Clean shutdown 時
      當clean shutdown 時,checkpoint會進行,並且此時datafile的start scn和控制檔案裡的stop scn會相同, 等到open時,Oracle檢查datafile header中的start scn和存於control file中的datafile的scn是否相同, 如果相同,接著檢查datafile header中的start scn和control file中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
二. 例項恢復的具體過程:
    當資料庫突然崩潰,而還沒有來得及將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來判斷需或者不需例項恢復。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29654823/viewspace-2127804/,如需轉載,請註明出處,否則將追究法律責任。

相關文章