需了解死鎖先看這一篇
死鎖是如何被發(fā)現(xiàn)和解決的?這篇文章告訴你
一、死鎖的產生原因
- 死鎖發(fā)生在兩個或多個事務相互等待對方釋放鎖,導致它們都無法繼續(xù)執(zhí)行的情況,形成死鎖。
- 這種情況在并發(fā)高的系統(tǒng)中比較常見,尤其是在多個事務同時操作相同的數據時。
常見場景包括:
- 不同順序訪問資源:事務A先操作表1再操作表2,事務B先操作表2再操作表1。
- 索引缺失:全表掃描導致鎖范圍擴大,增加沖突概率。
- 長事務:事務長時間未提交,導致鎖持有時間過長。
二、死鎖場景復現(xiàn)(以MySQL為例)
- 復現(xiàn)死鎖可以幫助理解問題發(fā)生的條件,從而更好地預防和解決。
1. 準備測試表和數據
CREATE TABLE account (
id INT PRIMARY KEY,
balance DECIMAL(10,2)
);
INSERT INTO account VALUES (1, 1000.00), (2, 2000.00);
2. 模擬兩個事務交叉更新
事務A:先更新id=1,再更新id=2。
BEGIN;
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;
COMMIT;
事務B:先更新id=2,再更新id=1。
BEGIN;
UPDATE account SET balance = balance - 200 WHERE id = 2;
UPDATE account SET balance = balance + 200 WHERE id = 1;
COMMIT;
3. 觀察死鎖
- 按順序執(zhí)行事務A和事務B的
UPDATE
語句。 - 事務A嘗試更新id=2時,因事務B持有鎖而等待。
- 事務B嘗試更新id=1時,因事務A持有鎖而等待。
- 數據庫檢測到死鎖,自動回滾其中一個事務:
1205 - Lock wait timeout exceeded; try restarting transaction

三、解決死鎖的核心方法
- 常見的解決策略包括設置合理的事務隔離級別、優(yōu)化事務邏輯、使用超時機制、以及數據庫自動檢測和處理死鎖。
1. 數據庫自動處理
2. 代碼層優(yōu)化
- 統(tǒng)一資源訪問順序:所有事務按相同順序操作表或記錄。
UPDATE account SET ... WHERE id = 1;
UPDATE account SET ... WHERE id = 2;
- 減少事務粒度:避免長事務,盡快提交或回滾。
@Transactional(timeout = 5)
public void transfer() { ... }
- 使用樂觀鎖:通過版本號避免行鎖競爭。
UPDATE account
SET balance = 900, version = version + 1
WHERE id = 1 AND version = 1;
3. 數據庫配置調優(yōu)
4. 重試機制
四、死鎖分析工具
MySQL死鎖日志:
- 查看
SHOW ENGINE INNODB STATUS
輸出,分析TRANSACTION
和WAITING FOR THIS LOCK
部分。
pt-deadlock-logger(Percona工具):
實時監(jiān)控死鎖事件并記錄。
pt-deadlock-logger --user=root --password=123456 --run-time=10
性能模式(Performance Schema):
MySQL 5.6+開啟性能模式,監(jiān)控鎖等待事件。
SELECT * FROM performance_schema.events_transactions_current;

五、預防死鎖
- 事務設計原則:
- 短事務優(yōu)先,及時提交。
- 避免交叉更新多張表。
- 統(tǒng)一操作順序:
所有業(yè)務邏輯按固定順序訪問資源(如按主鍵升序操作)。 - 監(jiān)控與報警:
配置Prometheus監(jiān)控死鎖次數,超過閾值觸發(fā)告警。 - 壓力測試:
使用JMeter模擬并發(fā)事務,驗證死鎖概率。
六、總結
- 復現(xiàn)死鎖:通過交叉更新不同順序的資源,觀察數據庫自動回滾。
- 解決方案:
- 統(tǒng)一資源訪問順序,減少鎖競爭。
- 優(yōu)化索引和事務設計,降低死鎖概率。
- 結合重試機制和數據庫自動處理,提升系統(tǒng)容錯性。
- 關鍵工具:數據庫日志、性能分析工具、壓力測試框架。
轉自https://juejin.cn/post/7481837718718644274
該文章在 2025/3/17 10:33:31 編輯過