首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 為什麼會產生前滾與回滾:Redo/Undo 機制與崩潰恢復深度解析

     編輯:Oracle 資料庫基礎

核心觀念:DBWn 寫髒塊與 Commit 無直接關係

  • 交易修改先寫 **Redo Log Buffer** (含變更向量)、**Undo Segment** (舊映像),再修改 **Buffer Cache** 中資料塊 (變髒塊)。
  • Redo Buffer 由 **LGWR** 批次寫入 **Online Redo Log File** (觸發條件:Commit、1/3 滿、3MB、每 3 秒、Checkpoint)。
  • 髒塊由 **DBWn** 依 **Checkpoint** / **LRU** / **Tablespace Offline** 等條件寫入 **Datafile**。
  • 關鍵:DBWn 寫入髒塊**不檢查交易是否 Commit**。因此 Datafile 可能同時包含 **Committed** 與 **Uncommitted** 變更。

崩潰恢復兩階段

Phase 1: Rolling Forward (前滾 / Cache Recovery)

  • Instance 啟動 `MOUNT` → `OPEN` 時,SMON 讀取 Online Redo Log。
  • 重放 **所有** Redo Records (含 Committed & Uncommitted) 至 Datafile,將 Buffer Cache 丟失的修改補回。
  • 結果:Datafile 達到崩潰時刻一致狀態,**但包含未提交交易的變更**。
  • 資料庫 `OPEN` 可服務查詢,**未提交交易修改的資料列被鎖定 (TX Lock)**,其他 Session 存取會等待。

Phase 2: Rolling Back (回滾 / Transaction Recovery)

  • SMON (或前景進程首次存取被鎖資料) 讀取 **Undo Segment** (儲於 Datafile/Undo Tablespace)。
  • 對每個 **Uncommitted Transaction** 產生反向操作 (Insert → Delete, Update → Reverse Update, Delete → Insert) 並套用至 Datafile。
  • 釋放 TX Lock,交易徹底回滾。

為什麼需要這雙重機制?

機制保護目標關鍵差異
前滾**持久性** — 已 Commit 交易不丟失依賴 **Redo Log** (循序寫、高效)、LGWR 寫入不記錄 Commit 標記 (只記錄變更向量)
回滾**原子性** — 未 Commit 交易不生效依賴 **Undo Segment** (隨機讀寫)、Commit 才在 Redo/Undo 中標記 `INACTIVE`

Commit 觸發寫入 vs LGWR 背景寫入的本質區別

  • Commit:前景進程發出 `COMMIT` → LGWR **同步寫入** Redo Buffer 至 Redo Log File (確認 `LGWR` 完成才回應用戶) → 標記 Redo/Undo 中該交易 `COMMITTED` (SCN 推進)。
  • LGWR 背景寫入:定期/閾值觸發,**異步批次寫入** Redo Buffer,**不標記交易狀態**,寫到哪算哪。掉電時 Redo Log 截斷於最後完整寫入處。

因此:Commit 是唯一能同步通知資料庫引擎「交易完成」的指令,引擎據此在 Redo/Undo 打標記,成為前滾/回滾的判斷依據。

關鍵參數與監控

參數/視圖作用
FAST_START_MTTR_TARGET目標平均恢復時間 (秒),控制 Checkpoint 頻率,間接決定前滾量。
LOG_CHECKPOINT_INTERVAL / TIMEOUT舊參數,控制 Checkpoint 間隔 (Redo Log 切換/時間)。
V$INSTANCE_RECOVERY預估恢復時間、需讀取 Redo Blocks 數。
V$TRANSACTION / V$ROLLSTAT活躍交易、Undo 使用量、回滾進度。

常見誤區澄清

  • ❌ 「Commit 才寫 Datafile」 → ✅ Commit 只強制寫 Redo Log;Datafile 由 DBWn 異步寫入。
  • ❌「Rollback Segment 只在 Rollback 時用」 → ✅ 每個 DML 都產生 Undo (供讀一致性、Rollback、Flashback Query)。
  • ❌「前滾只重放 Committed Redo」 → ✅ 前滾重放 **所有** Redo (含 Uncommitted),回滾才清理 Uncommitted。
  • ❌「Uncommitted 資料不在 Datafile」 → ✅ 可能已被 DBWn 寫入 Datafile (髒塊刷盤),需回滾移除。

總結

Oracle 透過 **Redo Log (循序、高效、持久)** 保證 Commit 不丟失 (前滾),透過 **Undo Segment (隨機、版本化)** 保證 Uncommitted 不生效 (回滾)。**Commit 觸發 LGWR 同步寫入並打標記**是連結兩者的關鍵。理解此機制,才能正確配置 `FAST_START_MTTR_TARGET`、設計備份恢復策略 (RMAN 架構即建立於 Redo/Undo 之上)、排查 `ORA-01555 Snapshot Too Old` 等核心問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved