核心觀念: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` 等核心問題。