為什麼 ORACLE 記憶體恢復在實例恢復過程中會創建未送出的塊?
以下是 ORACLE 書籍的節選
在記憶體恢復期間,Oracle 會重播自上次檢查點以來線上重做日誌文件中的事務。在此前滾操作期間,已送出和未送出的更改都將應用於數據文件。在前滾操作結束時,數據文件將具有已送出更改、寫入數據文件以釋放緩衝區高速記憶體空間的未送出更改以及前滾操作應用的未送出更改。記憶體恢復完成後即可打開數據庫。
上面粗體的句子是我不明白的。重做日誌文件如何生成未送出的數據,因為它的所有資訊都是在 COMMIT 之後記錄的?
此外它說
在實例恢復的事務恢復階段,Oracle 應用撤消塊來回滾數據塊中未送出的更改,這些更改要麼在實例崩潰之前寫入,要麼在記憶體恢復期間由前滾操作進行。
我知道如果在沒有事先送出的情況下將臟塊寫入磁碟(如果可能的話),在事務恢復期間,可以使用撤消塊來回滾它們。但是如何使用撤消塊來回滾在記憶體恢復期間重播重做日誌引入的未送出的更改(這些更改是什麼……)?
嗯我不明白,因為線上重做日誌應該只包含送出的資訊,在實例恢復期間創建未送出的資訊。
重做日誌文件如何生成未送出的數據,因為它的所有資訊都是在 COMMIT 之後記錄的?
LGWR
程序在以下情況下將重做日誌從重做日誌緩衝區記憶體刷新到線上重做日誌文件:
- 使用者明確送出。
- 重做日誌緩衝區中三分之一的空間已被填滿。
- 自上次重做刷新以來已經過去了三秒鐘。
DBWn
程序將臟緩衝區寫入磁碟。這些都觸發重做刷新,其中可能包括未送出的事務。
但是,如何使用撤消塊來回滾在記憶體恢復期間重播重做日誌引入的未送出的更改(無論如何這些更改是什麼……)?
讓我舉個例子,假設你有一個數據塊,其中包含一行單列的值
5
。您只需嘗試使用update tbl set col1=6
. 在此過程中,會生成 undo 以重現其原始值 is5
並生成 redo 以回复事務,這意味著重現最新值 is6
。接下來,如果此事務未送出並且不幸實例崩潰,則在下一次啟動期間,Oracle(特別
SMON
是程序)將需要恢復的塊放入緩衝區記憶體並使用重做日誌重新應用更改,如果有人試圖讀取您之前修改過的行,Oracle 只需使用撤消將包含該行的數據塊回滾到其原始值 5。更新: 以下警報日誌摘錄自此部落格。
ALTER DATABASE OPEN Beginning crash recovery of 1 threads Started redo scan Completed redo scan read 80458 KB redo, 1721 data blocks need recovery Started redo application at Thread 1: logseq 490, block 52626 Recovery of Online Redo Log: Thread 1 Group 1 Seq 490 Reading mem 0 Mem# 0: /home/oracle/app/oracle/oradata/orcl/redo01.log Recovery of Online Redo Log: Thread 1 Group 2 Seq 491 Reading mem 0 Mem# 0: /home/oracle/app/oracle/oradata/orcl/redo02.log Recovery of Online Redo Log: Thread 1 Group 3 Seq 492 Reading mem 0 Mem# 0: /home/oracle/app/oracle/oradata/orcl/redo03.log Completed redo application of 15.26MB Completed crash recovery at Thread 1: logseq 492, block 31015, scn 6082434 1721 data blocks read, 1721 data blocks written, 80458 redo k-bytes read Sun Jan 09 00:50:27 2011
這清楚地表明塊號
1721
需要恢復。為了做到這一點,將塊載入到記憶體(緩衝區記憶體)並應用重做。塊在恢復後被寫回數據文件。Thomas Kyte 的 Oracle 架構專家第三版一書(第 9 章重做和撤消,重做和撤消如何協同工作,頁面)中也對此進行了解釋。
來自 ASKTOM
你好湯姆,
- 為了進行崩潰恢復,數據庫需要將數據塊(需要恢復)帶入 SGA。我可以知道哪個過程會帶來它們嗎?
謝謝
跟進
smon 將在恢復階段讀取它們並對其應用重做。