oracle的redo和undo

追求完美9196發表於2024-07-08

1 redo

1.1 redo是什麼

oracle資料庫幾乎所有的操作都會產生redo日誌。redo日誌可以分為線上redo日誌和歸檔redo日誌。當資料庫例項失敗時,資料庫會使用redo日誌恢復資料。

1.2 線上重做日誌和歸檔重做日誌

1.2.1 線上重做日誌

資料庫的操作產生的redo日誌會先存放在線上重做日誌中。線上重做日誌在oracle中至少有兩組重做日誌,每組重做日誌包含一個或者多個線上重做日誌檔案,同一組內的線上重做日誌內容完全一樣。日誌切換是指當一組線上重做日誌寫滿時,oracle清空下一組線上重做日誌並在下一組寫入重做日誌。所以,線上重做日誌是迴圈使用的。

1.2.2 歸檔重做日誌

如果資料庫開啟了日誌歸檔,當一組線上重做日誌填滿時,就會將這組線上重做日誌進行歸檔,這些歸檔的日誌就是歸檔重做日誌。

1.3 例項恢復和介質恢復

例項恢復一般是指資料庫例項發生故障,例如系統突然崩潰,使用shutdown abort關閉資料資料庫。資料庫重啟時就會自動進行例項恢復。例項恢復主要使用線上重做日誌進行恢復。
介質恢復是指執行資料庫的磁碟發生損壞,需要使用物理備份進行恢復。物理備份包括資料庫某個時間的快照以及歸檔重做日誌,線上重做日誌。

2 undo

2.1 undo是什麼

當我們對資料進行修改時,就會產生undo,undo儲存在undo段中。我們就是使用undo對修改但未提交的資料進行恢復的。

2.2 undo的作用

  1. 使用rollback時,利用undo將資料恢復到事務之前的樣子
  2. 為oracle的讀一致性提供資料保障
  3. flashback table使用undo將表資料恢復到之前某個時間點

3 提交(commit)和回滾(rollback)處理

3.1 提交(commit)

3.1.1 提交前的工作

通常commit是一個快速的操作,其處理時間和事務大小無關。因此,我們應該儘量避免將一個事務拆分進行多次提交。commit是一個快速的操作,這是因為大部分事務的工作在commit之前已經完成

  • 在SGA中生成已修改的資料塊
  • 在SGA中生成undo塊
  • 在SGA中生成前兩項的redo快取
  • 如果前面執行的比較久,可能SGA中一些快取資料已經寫入磁碟
  • 獲取所需要的鎖

3.1.2 當進行commit時,只需要完成剩下的工作

  • 為事務生成一個SCN。SCN是oracle的一個序列機制,用來保證事務的順序,並用來支援例項恢復。此外,它還用於oracle的讀一致性和檢查點。每commit一次,SCN就會增加
  • LWGR將還在redo快取中的redo寫入線上重做日誌。並將SCN記錄在線上重做日誌中。這一步才是資料庫真正的commit。此時事務條目會從V$TRANSACTION中被“刪除”
  • 釋放V$lock中記錄該事務的會話中的鎖,從而讓等待鎖的其他事務繼續進行。
  • 如果被修改的塊還在資料庫快取記憶體中,oracle會進行塊清除。塊清除是指清除資料庫塊首部的一些鎖資訊。
    從以上可以看出,commit需要做的工作中,耗時最長的是將redo快取中的redo寫入線上重做日誌。如果,commit進行多次,則需要進行多次等待。需要注意的是,PL/SQL對commit是特殊處理的。如果一個PL/SQL中有多個commit,資料庫不會在PL/SQL進行commit時等待redo快取中的redo寫入線上重做日誌,而是立刻返回。但是,當PL/SQL執行完,將控制權返回客戶端前,會等待LGWR將對應的所有redo快取寫入磁碟。雖然如此,也不建議在PL/SQL中使用多次commit。

3.2 回滾(rollback)

當我們進行rollback操作時,會做如下工作

  • 撤銷所有修改。oracle使用undo資料撤銷所做的修改。並將對應undo資料標記為已應用。例如之前插入了一條資料,ROLLBACK會將其刪除。

  • 釋放V$lock中記錄該事務的會話中的鎖,從而讓等待鎖的其他事務繼續進行。

    從以上工作可以看出,rollback的操作的工作量會比commit大很多。commit最大的工作量僅僅是將redo快取寫入磁碟。

4 臨時表的redo和undo

臨時表(GLOBAL TEMPORARY TABLE)中的事務操作不會產生事務本身的redo,但是會產生undo。undo也會有對應redo,因此臨時表也會redo。但是可以透過設定引數TEMP_UNDO_ENABLED來將臨時表的undo放在臨時表空間中,由於臨時表空間的任何資料變更都不會產生redo,所以當這個引數設定為TRUE時,任何臨時表上的DML都會產生很少甚至不產生redo。
我們可以在會話和系統級別設定引數TEMP_UNDO_ENABLED,下面我們將這個引數在會話級別設定為 TRUE。
alter session set temp_undo_enabled=true;

5 資料庫如何利用redo進行例項恢復

一個事務commit成功是指該事務對應的redo日誌已經從redo快取中寫入線上重做日誌。資料庫進行例項恢復時,會讀取線上重做日誌的資料。
第一步是cache recovery,SMON根據最後一次檢查點後的線上重做日誌執行日誌內容,往前滾。這一步完成後,恢復所有commit的資料。線上重做日誌中可能有一些沒有commit的redo日誌,因此這一步完成後,資料庫快取記憶體中也會有一些未提交的資料庫。
第二步是Transaction Recovery,根據線上重做日誌的undo回滾未提交的資料。

相關文章