溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

mysql數據庫死鎖Deadlock found when trying to get lock怎么解決

發布時間:2022-02-28 16:31:56 來源:億速云 閱讀:4823 作者:iii 欄目:開發技術
# 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;

2. 間隙鎖沖突

在REPEATABLE READ隔離級別下,范圍查詢會產生間隙鎖:

-- 事務1
SELECT * FROM table WHERE id BETWEEN 1 AND 10 FOR UPDATE;

-- 事務2
INSERT INTO table(id) VALUES(5);  -- 被阻塞

3. 唯一鍵沖突

-- 事務1
INSERT INTO users(id, name) VALUES(1, 'Alice');

-- 事務2
INSERT INTO users(id, name) VALUES(1, 'Bob');  -- 死鎖可能發生

三、診斷MySQL死鎖

1. 查看最近死鎖信息

SHOW ENGINE INNODB STATUS\G

在輸出中查找LATEST DETECTED DEADLOCK部分。

2. 開啟死鎖日志

在my.cnf中配置:

[mysqld]
innodb_print_all_deadlocks = 1

3. 分析死鎖日志

典型死鎖日志包含: - 涉及的事務信息 - 持有的鎖和等待的鎖 - 最終被選為犧牲品(victim)的事務

四、解決MySQL死鎖的12種方法

1. 保持一致的訪問順序

確保所有事務按照相同的順序訪問表和行。

2. 減少事務范圍

-- 不推薦
START TRANSACTION;
-- 大量業務邏輯
COMMIT;

-- 推薦
START TRANSACTION;
-- 僅必要的數據庫操作
COMMIT;

3. 降低隔離級別

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

4. 添加合理的索引

-- 無索引的列會導致表鎖
ALTER TABLE orders ADD INDEX idx_customer_id(customer_id);

5. 控制鎖超時時間

SET innodb_lock_wait_timeout = 30;  -- 單位秒

6. 拆分大事務

將大事務拆分為多個小事務執行。

7. 使用樂觀鎖替代

UPDATE products 
SET stock = stock - 1, version = version + 1 
WHERE id = 100 AND version = 5;

8. 避免熱點數據

  • 賬戶余額等熱點數據考慮分片
  • 使用隊列緩沖寫操作

9. 使用SELECT … FOR UPDATE NOWT

SELECT * FROM table WHERE id = 1 FOR UPDATE NOWT;

10. 重試機制

應用程序捕獲死鎖異常后自動重試:

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))

11. 使用死鎖檢測工具

  • pt-deadlock-logger
  • MySQL Enterprise Monitor

12. 調整InnoDB參數

[mysqld]
innodb_deadlock_detect = ON  # 默認開啟
innodb_lock_wait_timeout = 50

五、高級解決方案

1. 應用層分布式鎖

// 使用Redis實現分布式鎖
String lockKey = "order_lock_" + orderId;
boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);

2. 數據庫設計優化

  • 避免長事務
  • 合理設計主鍵(避免隨機UUID等)
  • 考慮使用邏輯刪除替代物理刪除

3. 分庫分表策略

對高頻競爭的表進行水平拆分。

六、死鎖監控與預警

1. 配置監控

-- 監控鎖等待
SELECT * FROM performance_schema.events_waits_current 
WHERE EVENT_NAME LIKE '%lock%';

-- 監控死鎖次數
SHOW STATUS LIKE 'innodb_row_lock%';

2. 設置告警規則

  • 每分鐘死鎖次數 > 3次觸發告警
  • 鎖等待時間 > 5秒觸發告警

七、真實案例分析

案例1:電商訂單系統

現象:下單時頻繁出現死鎖
原因:庫存扣減和訂單創建未按固定順序
解決方案: 1. 先鎖商品記錄,再鎖優惠券記錄 2. 引入Redis預減庫存

案例2:社交網絡點贊系統

現象:熱點帖子點贊死鎖
解決方案: 1. 使用計數器表+定期合并 2. 客戶端批量提交

八、總結

MySQL死鎖是并發系統中常見問題,通過以下原則可以有效減少死鎖: 1. 預防:統一資源訪問順序,減少事務持有時間 2. 檢測:建立完善的監控體系 3. 恢復:實現自動重試機制 4. 優化:持續分析業務場景,針對性優化

最佳實踐建議:在開發環境開啟完整的死鎖日志記錄,定期分析潛在的死鎖風險,將死鎖處理方案納入代碼評審標準。

參考資料

  1. MySQL 8.0官方文檔 - Deadlocks in InnoDB
  2. 《高性能MySQL》第6章 - 鎖和事務
  3. Oracle InnoDB Locking and Transaction Handling

”`

這篇文章共計約2100字,采用Markdown格式編寫,包含了: - 死鎖原理說明 - 常見場景分析 - 診斷方法 - 12種解決方案 - 高級優化建議 - 真實案例 - 監控預警方案 - 總結與最佳實踐

內容結構清晰,既有理論知識也有實操方案,適合DBA和開發人員閱讀參考。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女