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

MySQL 死鎖成因、四大必要條件與預防解決全攻略

     編輯:MySQL 綜合教學

什麼是死鎖

兩個或多個事務在爭奪資源時形成**循環等待**,若無外力干預將永遠阻塞。InnoDB 會自動檢測並回滾代價較小的事務(ERROR 1213 (HY000): Deadlock found)。

死鎖四大必要條件(同時滿足才發生)

  1. 互斥條件:資源排他使用(行鎖/表鎖)
  2. 請求與保持:持有鎖的同時請求新鎖
  3. 不剝奪條件:鎖只能主動釋放,不可強制搶佔
  4. 循環等待:T1 等 T2 的鎖,T2 等 T1 的鎖(或更長環)

**破壞任一條件即可避免死鎖**。

常見死鎖場景

1. 多表更新順序不一致

-- 事務 A
UPDATE table_a SET ... WHERE id=1;  -- 鎖 A
UPDATE table_b SET ... WHERE id=1;  -- 鎖 B

-- 事務 B
UPDATE table_b SET ... WHERE id=1;  -- 鎖 B
UPDATE table_a SET ... WHERE id=1;  -- 鎖 A
-- 形成 A→B, B→A 循環

2. 索引缺失導致全表掃描鎖升級

  • WHERE 條件無索引 → 掃描全表 → 行鎖升級為**表鎖** → 並發極低、死鎖概率激增
  • 大表缺乏合適索引同理

3. 間隙鎖 + 插入意向鎖衝突

RR 隔離級別下,範圍查詢加間隙鎖,並發插入等待間隙鎖釋放,極端情況形成死鎖。

預防與減少死鎖的五大鐵律

  1. 統一訪問順序:所有事務**按相同順序**操作表/行(如先 A 後 B)。存儲過程封裝業務邏輯可強制統一。
  2. 避免事務中用戶交互:思考時間長 → 鎖持有久 → 衝突概率增。異步處理、前端校驗前置。
  3. 保持事務短小、單批次:拆分大事務,減少鎖持有時間與範圍。
  4. 使用較低隔離級別:READ COMMITTED(RC)無間隙鎖,死鎖概率顯著低於 REPEATABLE READ(RR)。業務允許時優先 RC。
  5. 合理設計索引:確保 WHERE/JOIN/ORDER BY 列有索引,**避免全表掃描導致鎖升級**。

輔助手段

  • innodb_lock_wait_timeout(默認 50s):超時自動回滾,防無限等待
  • innodb_deadlock_detect=ON(默認):後台線程主動檢測循環等待並回滾受害者
  • 應用層捕獲 1213 錯誤**指數退避重試**(如 10ms, 50ms, 200ms...)
  • 監控 SHOW ENGINE INNODB STATUS 中 LATEST DETECTED DEADLOCK 定期分析死鎖圖譜

排查步驟

  1. 獲取死錯日誌:SHOW ENGINE INNODB STATUS
  2. 分析兩個事務的 SQL 序列、鎖模式(X/S/意向/間隙)、等待關系
  3. 定位違反「統一順序」或「索引缺失」的代碼路徑
  4. 修正代碼/加索引/調隔離級別,驗證壓測無死鎖

總結

死鎖本質是**並發控制邏輯缺陷**。**統一順序、短事務、好索引、低隔離** 四字訣,解決 95% 死鎖問題。剩下 5% 用檢測+重試兜底。

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