首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle 事務隔離級別完整解析:從 ANSI 標準到實作機制

     編輯:Oracle 資料庫相關知識

資料庫並發控制的核心在於隔離級別。本文系統梳理 ANSI SQL-92 定義的四大隔離級別、三大經典異常現象,並深入剖析 Oracle 獨特的「讀不阻塞寫、寫不阻塞讀」多版本一致性讀(MVCC)實作機制。

三大並發異常現象

異常場景描述口訣
髒讀T1 修改未提交,T2 讀到;T1 回滾,T2 讀到無效資料讀到未提交
不可重複讀T1 讀同一列兩次,中間 T2 修改並提交,兩次結果不同同一查詢結果變
幻讀T1 按條件查兩次,中間 T2 插入符合條件新列,第二次多出列查詢結果集變多

ANSI 四大隔離級別與允許異常

隔離級別髒讀不可重複讀幻讀備註
READ UNCOMMITTED允許允許允許極少資料庫預設
READ COMMITTED禁止允許允許Oracle、PostgreSQL、SQL Server 預設
REPEATABLE READ禁止禁止允許MySQL InnoDB 預設
SERIALIZABLE禁止禁止禁止最高隔離,效能最差

Oracle 實際支援的隔離級別

Oracle **僅支援** READ COMMITTED(預設)與 SERIALIZABLE 兩種,不支援 READ UNCOMMITTED、REPEATABLE READ。

READ COMMITTED(語句級一致性)

  • 每個 SQL 陳述式只看該陳述式開始時已提交的資料
  • 利用 **Undo Segment** 構建一致性讀映像(CR Block),讀取不等待鎖釋放
  • 同一事務中兩次相同查詢可能結果不同(允許不可重複讀、幻讀)

SERIALIZABLE(事務級一致性)

  • 事務開始瞬間建立快照 SCN,整個事務只看該 SCN 之前已提交的資料
  • 若嘗試修改被其他事務已修改且提交的列,拋出 ORA-08177: can't serialize access for this transaction
  • 應用層需捕獲該異常並重試整個事務
  • 設定方式:SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;(必須在事務第一條 DML 前執行)

Oracle MVCC 核心優勢:讀寫不互斥

Oracle 透過 Undo Segment 保存舊版本資料塊,實現「讀不阻塞寫、寫不阻塞讀」。這與 SQL Server 預設使用鎖實現隔離(讀寫互斥)形成鮮明對比,是 Oracle 高併發效能的基石。

實戰測試腳本(需兩個 Session)

-- Session 1: 設定 SERIALIZABLE
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM t WHERE id = 1;  -- 假設回傳 name='A'
-- 暫停,不提交

-- Session 2: 修改並提交
UPDATE t SET name = 'B' WHERE id = 1;
COMMIT;

-- Session 1: 再次查詢
SELECT * FROM t WHERE id = 1;  -- 仍回傳 'A'(快照隔離)
-- 嘗試更新同一列
UPDATE t SET name = 'C' WHERE id = 1;  -- 拋 ORA-08177

-- Session 3: 新開事務(READ COMMITTED)
SELECT * FROM t WHERE id = 1;  -- 看到 'B'(已提交版本)

事務開始時間點定義

  1. 連接資料庫並執行第一條 DML(INSERT/UPDATE/DELETE/MERGE)
  2. 前一事務結束(COMMIT/ROLLBACK)後,執行下一條 DML

SELECT 不會啟動事務。

調優建議

  • **99% 應用使用預設 READ COMMITTED 即可**,配合樂觀鎖(版本號/時間戳)處理業務層並發衝突
  • 極少數財務結帳、庫存扣減等強一致性場景才考慮 SERIALIZABLE,並做好重試邏輯
  • 監控 V$TRANSACTION、V$UNDOSTAT 確保 Undo 表空間與 UNDO_RETENTION 滿足長查詢需求,避免 ORA-01555

理解隔離級別不是背誦定義,而是預判業務場景下的並發行為,選擇最小代價滿足正確性的策略。

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