一條 DELETE 背後,Oracle 在毫秒級內完成了緩存讀取、Redo 生成、Undo 記錄、塊標記、鎖管理、提交協議等精密協作。本文將 DELETE 階段 與 COMMIT 階段 拆解為原子步驟,還原事務處理的核心軌跡,為理解鎖競爭、恢復機制、效能調優奠基。
一、DELETE 執行流程 (5 步)
- 讀取資料塊進 Buffer Cache: Server Process 根據 RowID/Index 定位塊,若不在 Cache,申請 Cache Buffer Chain Latch,從磁碟讀入 LRU 列表頭部的空閒桶 (或覆蓋 Non-Dirty Buffer)。
- 生成 Redo Entry 寫入 Redo Log Buffer: 記錄刪除操作元數據 (表空間號、文件號、塊號、Row 目錄槽位、舊值用於回滾),需 Redo Allocation Latch / Redo Copy Latch 保護。
- 在 Undo Segment Header 事務表創建 Undo Slot: 分配事務槽位 (XID),標記狀態為 ACTIVE,記錄 Undo Segment Header 位置。
- 構建前映像 (Before Image) 寫入 Undo Block: 將被刪除的整行數據 (所有列值) 複製到 Undo Segment 的 Undo Block,供回滾時恢復。Undo Block 同樣受 Buffer Cache 管理,變更同樣生成 Redo (遞迴)。
- 在 Buffer Cache 中標記刪除、塊變 Dirty: 資料塊 Row Directory 標記該槽位已刪除 (非物理移除),修改塊頭 SCN,將塊掛入 Dirty Buffer List (LRU 臟鏈),等待 DBWn 刷盤。
二、COMMIT 執行流程 (6 步)
- 生成提交 SCN (Commit SCN): 從全域 SCN 機制獲取單調遞增 SCN,標記事務提交時刻。
- 更新 Undo Segment Header 事務表: 將事務槽位狀態從 ACTIVE 改為 COMMITTED,記錄 Commit SCN。
- LGWR 刷新 Redo Log Buffer 至 Online Redo Log File (強制同步寫入): 關鍵:LGWR 必須確認寫入磁碟完成才返回,保證持久性。包含 Commit Record (OPCODE=5.4) 及該事務所有 Redo Entry。
- 快速提交 : 若資料塊仍在 Buffer Cache,直接在塊頭寫入 Commit SCN (清理 ITL Entry),標記事務完成,無需立即刷盤。
- 延遲塊清理 : 若資料塊已被 DBWn 刷盤 (不在 Cache),下次訪問該塊的進程讀取塊頭 ITL,發現事務 COMMITTED,自動清理 ITL (寫入 Commit SCN),並將塊標記為已清理。
- 釋放行級鎖 (TX Lock): 實際釋放發生在 DBWn 將該塊寫入磁碟後 (或快速提交路徑中),而非 Commit 瞬間。
三、核心機制深度剖析
SCN (System Change Number) —— 全域時鐘
- 單調遞增、實例唯一、分散式環境全域協調。
- 用於:一致性讀判斷 (查詢 SCN vs 塊頭 SCN)、恢復排序、檢查點推進、分散式事務協調。
快速提交 vs 延遲塊清理
| 特性 | 快速提交 | 延遲塊清理 |
| 觸發條件 | Commit 時塊在 Buffer Cache | Commit 時塊已刷盤 (不在 Cache) |
| 動作 | 直接改塊頭 ITL 寫 Commit SCN | 下次訪問塊時由訪問進程清理 |
| 優勢 | 無額外 I/O、Commit 延遲極低 | 避免 Commit 時強制讀回塊 |
| 風險 | 大量提交未清理塊積壓 | 訪問延遲抖動、Undo 保留壓力 |
Instance Recovery (SMON) 雙軌制
- 前滾 : 掃描 Redo Log (從最後 Checkpoint SCN),重做所有 Committed 事務的修改 (含 Commit 後未刷盤的)。
- 回滾 : 利用 Undo 回滾所有 Uncommitted 事務的修改 (含已刷盤但未提交的)。
- 關鍵順序 : DBWn 寫塊前 → LGWR 必須先寫 Redo (Write-Ahead Logging, WAL),保證恢復邏輯自洽。
斷電場景推演
- Commit 後、DBWn 未刷盤 → 重啟 → SMON 前滾 (Redo 有 Commit Record) → 數據持久化。
- 未 Commit、DBWn 已刷盤 (WAL 保證 Redo 先寫) → 重啟 → SMON 回滾 (Undo 恢復舊值) → 數據如事務未發生。
四、實戰啟示
- 大量 DELETE 必須分批 Commit: 避免單事務 Undo 爆滿、Redo Log Switch 飆升、鎖持有時間過長阻塞併發。
- 監控
V$TRANSACTION、V$ROLLSTAT、V$WAITSTAT (undo header/block contention)。
- 適當調大
UNDO_RETENTION、Undo Tablespace,支援長查詢一致性讀與 Flashback。
- Commit 後立即查詢同塊可能觸發延遲塊清理,若極敏感可考慮
DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY 等手動干預 (極罕見)。
結語
DELETE + COMMIT 看似簡單,實則串聯了 Buffer Cache、Redo Log Buffer、Undo Segment、SCN、LGWR/DBWn/SMON 三大背景進程、鎖/鎖存器、WAL 協議、快速提交/延遲清理雙路徑。透徹理解這條鏈路,才能在死鎖分析、恢復演練、大批量刪除優化、審計合規中,做出精準、自信的技術判斷。
- 上一篇文章: Java Swing 視窗背景圖片實作:LayeredPane 分層佈局技巧
- 下一篇文章: Oracle DECODE 函數完整指南:語法、與 CASE 對比、資料型別陷阱與實戰範例
Copyright ©
程式碼之家 All Rights Reserved