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

Oracle 鎖機制深度解析:悲觀鎖與樂觀鎖的原理、語法與實戰對比

     編輯:Oracle 資料庫基礎

前言:為什麼需要鎖?

資料庫為追求高並發效能,皆實作並發控制機制。但並發帶來資料存取衝突(髒讀、不可重複讀、幻讀、更新遺失),鎖定正是解決衝突的核心手段。主流資料庫採用兩大鎖策略:

  • 悲觀鎖:假設衝突必發生,讀取階段即加鎖,阻塞其他寫入。
  • 樂觀鎖:假設衝突罕見,提交階段才檢測版本/時間戳,衝突則回滾重試。

Oracle 的行級鎖優勢

SQL Server 早期採頁級鎖(Page Lock),同表並發插入需排隊;Oracle 設計為行級鎖,僅鎖定被修改的資料列,其他列完全不受影響,並發插入/更新效能極高,幾乎無阻塞。

悲觀鎖在 Oracle 的兩種語法

1. SELECT ... FOR UPDATE(預設 WAIT 模式)

-- Session 1
SELECT * FROM test WHERE id = 10 FOR UPDATE;
-- 該列被鎖定,Session 1 未 COMMIT/ROLLBACK 前,其他 Session 執行相同語句會阻塞等待

特點:第二個 Session 執行 SELECT ... FOR UPDATE 會 Hang 住,直到第一個 Session 釋放鎖。若第二個 Session 執行 不帶 FOR UPDATE 的純查詢,則不阻塞,Oracle 多版本一致性讀(MVCC)保證讀到提交前的舊版本。

2. SELECT ... FOR UPDATE NOWAIT

SELECT * FROM test WHERE id = 10 FOR UPDATE NOWAIT;

若目標列已被鎖定,立即拋出 ORA-00054: resource busy and acquire with NOWAIT specified,應用層可捕獲異常並決定重試或報錯,避免無限期等待。

DML 操作與鎖的互動

當 Session 1 持有 FOR UPDATE 鎖時:

  • Session 2 執行 UPDATE test SET value=2 WHERE id=10 同樣會阻塞,直到 Session 1 釋放鎖。
  • Session 2 的 UPDATE 成功後,該列再次被 Session 2 的 排他鎖(TX Lock) 持有,直到 Session 2 COMMIT/ROLLBACK。

結論:Oracle 的悲觀鎖本質是利用 資料庫連線(Session)持有的 TX 鎖 實現行級排他,效能損耗極小,但需注意應用邏輯避免死鎖。

樂觀鎖實作模式(應用層實作)

Oracle 內建無樂觀鎖語法,常見做法:

  1. 表新增 VERSION NUMBER 或 LAST_UPDATED TIMESTAMP 欄位。
  2. 讀取時帶出版本號。
  3. 更新時帶入舊版本號作為 WHERE 條件:
    UPDATE t SET val=:new, version=version+1 WHERE id=:id AND version=:old_version
  4. 若 SQL%ROWCOUNT = 0 表示版本已變,拋出樂觀鎖異常,應用層重新讀取並重試。

選型建議

場景推薦策略
高衝突、短事務、需強一致性(如扣款、庫存扣減)悲觀鎖 FOR UPDATE NOWAIT + 應用層重試
低衝突、長事務、用戶思考時間長(如表單編輯)樂觀鎖(版本號/時間戳)
純查詢報表無需加鎖,依賴 MVCC 一致性讀
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved