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

InnoDB 死鎖異常處理實戰:從程式碼重試到原理深度解析

     編輯:MySQL 資料庫相關知識

現象與影響

應用執行 UPDATE 時拋出 DeadlockLoserDataAccessException,資料庫自動回滾重試,用戶感知為操作卡頓,監控系統持續報警。

應用層解決方案:指數退避重試

private void updateWithDeadLockRetry(Mapper mapper, Record record) {
    int maxRetries = 5;
    for (int attempt = 0; attempt < maxRetries; attempt++) {
        try {
            mapper.updateByPrimaryKeySelective(record);
            return; // 成功即返回
        } catch (DeadlockLoserDataAccessException e) {
            if (attempt == maxRetries - 1) throw e; // 最後一次仍失敗則拋出
            long sleepMs = (long) (Math.random() * 500) + (attempt * 100); // 指數退避+抖動
            Thread.sleep(sleepMs);
        }
    }
}

關鍵點: 限制重試次數、引入隨機延遲避免雷群效應、記錄重試日誌便於事後分析。

死鎖原理深度剖析

InnoDB 鎖類型

  • 共享鎖(S):SELECT ... LOCK IN SHARE MODE 獲取,允許並發讀、阻塞寫
  • 排他鎖(X):UPDATE/DELETE 獲取,阻塞所有其他鎖

經典死鎖場景推演

  1. 事務 A:SELECT * FROM t WHERE i=1 LOCK IN SHARE MODE → 持有 S 鎖
  2. 事務 B:DELETE FROM t WHERE i=1 → 需要 X 鎖,被 A 的 S 鎖阻塞,等待中
  3. 事務 A:DELETE FROM t WHERE i=1 → 需要 X 鎖,但 B 已持有 X 鎖等待 → 循環等待形成死鎖

InnoDB 偵測到死鎖後,選擇代價較小的事務(通常是修改行數較少者)為犧牲者回滾,釋放鎖資源,另一事務繼續執行。

預防最佳實踐

  • 固定存取順序:多表關聯更新時,所有事務遵循相同表順序、行順序(如按主鍵排序)
  • 縮短事務長度:避免在事務中進行 RPC 呼叫、複雜計算、大量資料處理
  • 合理索引:減少全表掃描鎖定過多行記錄
  • 降低隔離級別:評估業務可接受下,使用 READ COMMITTED 減少間隙鎖
  • 監控告警:SHOW ENGINE INNODB STATUS 定期檢視死鎖歷史
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved