# MySQL數據庫死鎖Deadlock found when trying to get lock怎么解決
## 一、什么是MySQL死鎖
死鎖(Deadlock)是指兩個或多個事務在執行過程中,因爭奪資源而造成的一種互相等待的現象。當MySQL檢測到這種循環依賴關系時,會立即終止其中一個事務的執行,并拋出錯誤:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
### 死鎖的四個必要條件
1. **互斥條件**:資源一次只能被一個事務占用
2. **請求與保持條件**:事務持有資源的同時請求新的資源
3. **不剝奪條件**:已分配的資源不能被其他事務強行剝奪
4. **循環等待條件**:多個事務形成頭尾相接的等待環路
## 二、MySQL死鎖的常見場景
### 1. 不同順序的加鎖操作
```sql
-- 事務1
UPDATE table_a SET ... WHERE id = 1;
UPDATE table_b SET ... WHERE id = 2;
-- 事務2
UPDATE table_b SET ... WHERE id = 2;
UPDATE table_a SET ... WHERE id = 1;
在REPEATABLE READ隔離級別下,范圍查詢會產生間隙鎖:
-- 事務1
SELECT * FROM table WHERE id BETWEEN 1 AND 10 FOR UPDATE;
-- 事務2
INSERT INTO table(id) VALUES(5); -- 被阻塞
-- 事務1
INSERT INTO users(id, name) VALUES(1, 'Alice');
-- 事務2
INSERT INTO users(id, name) VALUES(1, 'Bob'); -- 死鎖可能發生
SHOW ENGINE INNODB STATUS\G
在輸出中查找LATEST DETECTED DEADLOCK
部分。
在my.cnf中配置:
[mysqld]
innodb_print_all_deadlocks = 1
典型死鎖日志包含: - 涉及的事務信息 - 持有的鎖和等待的鎖 - 最終被選為犧牲品(victim)的事務
確保所有事務按照相同的順序訪問表和行。
-- 不推薦
START TRANSACTION;
-- 大量業務邏輯
COMMIT;
-- 推薦
START TRANSACTION;
-- 僅必要的數據庫操作
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 無索引的列會導致表鎖
ALTER TABLE orders ADD INDEX idx_customer_id(customer_id);
SET innodb_lock_wait_timeout = 30; -- 單位秒
將大事務拆分為多個小事務執行。
UPDATE products
SET stock = stock - 1, version = version + 1
WHERE id = 100 AND version = 5;
SELECT * FROM table WHERE id = 1 FOR UPDATE NOWT;
應用程序捕獲死鎖異常后自動重試:
max_retries = 3
for attempt in range(max_retries):
try:
execute_transaction()
break
except DeadlockException:
if attempt == max_retries - 1:
raise
sleep(random.uniform(0, 0.1))
[mysqld]
innodb_deadlock_detect = ON # 默認開啟
innodb_lock_wait_timeout = 50
// 使用Redis實現分布式鎖
String lockKey = "order_lock_" + orderId;
boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
對高頻競爭的表進行水平拆分。
-- 監控鎖等待
SELECT * FROM performance_schema.events_waits_current
WHERE EVENT_NAME LIKE '%lock%';
-- 監控死鎖次數
SHOW STATUS LIKE 'innodb_row_lock%';
現象:下單時頻繁出現死鎖
原因:庫存扣減和訂單創建未按固定順序
解決方案:
1. 先鎖商品記錄,再鎖優惠券記錄
2. 引入Redis預減庫存
現象:熱點帖子點贊死鎖
解決方案:
1. 使用計數器表+定期合并
2. 客戶端批量提交
MySQL死鎖是并發系統中常見問題,通過以下原則可以有效減少死鎖: 1. 預防:統一資源訪問順序,減少事務持有時間 2. 檢測:建立完善的監控體系 3. 恢復:實現自動重試機制 4. 優化:持續分析業務場景,針對性優化
最佳實踐建議:在開發環境開啟完整的死鎖日志記錄,定期分析潛在的死鎖風險,將死鎖處理方案納入代碼評審標準。
”`
這篇文章共計約2100字,采用Markdown格式編寫,包含了: - 死鎖原理說明 - 常見場景分析 - 診斷方法 - 12種解決方案 - 高級優化建議 - 真實案例 - 監控預警方案 - 總結與最佳實踐
內容結構清晰,既有理論知識也有實操方案,適合DBA和開發人員閱讀參考。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。