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

Oracle 死鎖原理圖解:從阻塞到死鎖的必然演進與犧牲者選擇機制

     編輯:Oracle 資料庫基礎

死鎖是並發資料庫系統的經典難題。本文以「兩會話、兩表、各一列」最小模型,逐步演示從阻塞到死鎖的必然演進,解析 Oracle 死鎖偵測機制、犧牲者選擇邏輯、錯誤碼 ORA-00060 內容,並提供預防與排查實務指南。

一、最小死鎖復現模型

-- 建表
CREATE TABLE a (id NUMBER PRIMARY KEY);
CREATE TABLE b (id NUMBER PRIMARY KEY);
INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1);
COMMIT;

會話 A

UPDATE a SET id = 2 WHERE id = 1;  -- 鎖定表 A 第 1 列
-- 此處暫停,不提交

會話 B

UPDATE b SET id = 2 WHERE id = 1;  -- 鎖定表 B 第 1 列
-- 此處暫停,不提交

形成阻塞(非死鎖)

-- 會話 B 嘗試更新表 A
UPDATE a SET id = 3 WHERE id = 1;  -- 阻塞,等待會話 A 釋放鎖
-- 會話 A 此時若 COMMIT/ROLLBACK,會話 B 即可繼續 → 只是阻塞

形成死鎖

-- 會話 A 轉而嘗試更新表 B
UPDATE b SET id = 3 WHERE id = 1;  -- 死鎖!雙方互相等待對方釋放鎖

二、Oracle 死鎖偵測與處理流程

  1. 等待圖檢測:背景進程 LCK0 / LMD0 (RAC) 定期掃描等待圖,發現環狀等待。
  2. 選擇犧牲者:根據內部演算法(通常是「執行較少工作」、「較新會話」、「較低權限」),強制其中一個陳述式回滾。
  3. 回傳錯誤:犧牲者會話收到 ORA-00060: deadlock detected while waiting for resource,並附帶追蹤檔路徑。
  4. 釋放鎖:犧牲者陳述式回滾,持有的鎖釋放,另一會話繼續執行。

三、ORA-00060 追蹤檔關鍵資訊


*** 2024-01-15 10:30:45.123
DEADLOCK DETECTED ( ORA-00060 )
[Transaction Deadlock]

The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or in issuing incorrect ad-hoc SQL.

Current SQL Statement for this session (Session 1):
UPDATE b SET id = 3 WHERE id = 1

Waiter (Session 1) holds:
  TM lock on table A (mode 3 - Row-X)
Waiter (Session 1) waits for:
  TX lock on table B (mode 6 - Exclusive)

Holder (Session 2) holds:
  TM lock on table B (mode 3 - Row-X)
Holder (Session 2) waits for:
  TX lock on table A (mode 6 - Exclusive)

追蹤檔位置:USER_DUMP_DEST / DIAGNOSTIC_DEST 下的 ora_.trc。

四、死鎖 vs 阻塞:關鍵差異表

維度阻塞死鎖
等待鏈單向(A 等 B)環狀(A 等 B,B 等 A)
自動解除否(需等待持有者提交/回滾)是(Oracle 強制犧牲者回滾)
錯誤碼無(單純等待)ORA-00060
業務影響延遲其中一筆交易全部回滾

五、預防死鎖的五大鐵律

  1. 統一存取順序:所有會話以相同順序存取表(如先 A 後 B),打破環狀等待必要條件。
  2. 縮短交易長度:盡早提交/回滾,減少鎖持有時間。
  3. 避免長交易中查詢用戶輸入:人工介入會無限延長鎖持有。
  4. 使用 SELECT ... FOR UPDATE NOWAIT / SKIP LOCKED:快速失敗或跳過已鎖列,不進入等待。
  5. 索引外鍵欄位:未索引外鍵導致父表鎖升級為表級鎖,大幅增加死鎖機率。

六、排查與監控實務

  • 即時檢視:SELECT * FROM v$session_wait WHERE event LIKE 'enq%';
  • 歷史分析:DBA_HIST_ACTIVE_SESS_HISTORY 過濾 event = 'enq: TX - row lock contention'。
  • 告警設定:Enterprise Manager / Cloud Control 設定 ORA-00060 郵件告警。
  • 應用層重試:捕獲 SQLState 61000 / ErrorCode 60,指數退避重試(最多 3 次)。

死鎖本質是應用設計缺陷在資料庫層面的投影。透過統一存取順序、縮短交易、索引外鍵,可從根源消除 90% 以上死鎖;剩餘極少數由 Oracle 自動偵測犧牲,配合應用層重試機制,即可構建健壯的高併發系統。

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