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

Oracle SELECT ... FOR UPDATE NOWAIT:非阻塞鎖定實現並發控制

     編輯:Oracle 資料庫相關知識

FOR UPDATE NOWAIT 讓查詢在目標行已被鎖定時立即拋出異常 (ORA-00054) 而非等待,適用於高併發下需快速失敗、避免長時間阻塞的業務場景。

語法與行為

SELECT * FROM table_name
WHERE condition
FOR UPDATE NOWAIT;
  • 目標行**未被鎖定** → 正常返回,並加上排他鎖 (Row Exclusive Lock)
  • 目標行**已被鎖定** → 立即拋出 ORA-00054: resource busy and acquire with NOWAIT specified
  • 鎖持有至交易 COMMIT 或 ROLLBACK 釋放

應用場景一:單筆資料查詢加鎖處理

-- 業務邏輯:查詢商品圖片並標記處理中
SELECT *
FROM hold_mc_site_product_pic pic
WHERE pic.id = 730127
FOR UPDATE NOWAIT;

若返回成功 → 取得鎖,執行後續業務邏輯 → COMMIT 釋放。
若拋出 ORA-00054 → 表示該筆資料正被他人處理,業務邏輯可選擇跳過、重試或通知用戶。

應用場景二:多執行緒批次處理並發控制

  1. 主執行緒查詢待處理清單 (如 STATUS='PENDING')
  2. 各工作執行緒依序對單筆資料執行 SELECT ... FOR UPDATE NOWAIT
  3. 成功取得鎖 → 處理業務 → 更新狀態 → COMMIT
  4. 失敗 (ORA-00054) → 該筆被其他執行緒處理中 → 繼續下一筆

此模式實現**「樂觀佇列」**:資料庫層面保證同一筆資料同一時間僅有一個執行緒處理,無需應用層分散式鎖。

對比:FOR UPDATE vs FOR UPDATE NOWAIT vs FOR UPDATE WAIT n

語法行為適用場景
FOR UPDATE無限期等待鎖釋放低併發、容忍等待
FOR UPDATE NOWAIT立即失敗拋出 ORA-00054高併發、需快速失敗、避免阻塞
FOR UPDATE WAIT 5最多等待 5 秒再失敗折衷方案、允許短暫等待
FOR UPDATE SKIP LOCKED (11g+)跳過已鎖定行,只返回可鎖定行佇列消費者模式、批次處理最佳

最佳實務建議

  • 搭配 EXCEPTION WHEN OTHERS THEN IF SQLCODE = -54 THEN ... 處理 ORA-00054
  • 交易時間盡量短,避免長時間持有鎖影響併發
  • 11g 以上優先考慮 SKIP LOCKED 實現無鎖佇列消費
  • 監控 V$SESSION_WAIT 事件 enq: TX - row lock contention 發現熱點
核心價值:NOWAIT 將「等待」轉為「快速失敗」,讓應用層掌握流控主動權,是高併發系統資料庫層面的關鍵設計模式。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved