萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 死鎖分析與解決:從 SHOW PROCESSLIST 到索引優化

死鎖基礎知識

  • 表級鎖(MyISAM、MEMORY):不會死鎖,但並發差
  • 行級鎖(InnoDB):高並發下易發生死鎖

緊急處理:殺掉阻塞執行緒

SHOW PROCESSLIST;  -- 找到 State=Locked 或 Time 較大的 Id
KILL ;

根因分析:找出死鎖 SQL

SHOW ENGINE INNODB STATUS\G
-- 輸出中 LATEST DETECTED DEADLOCK 區塊會顯示:
-- 1. 兩條互相等待的 SQL
-- 2. 持有/等待的鎖模式(X/S)
-- 3. 事務隔離級別

常見死鎖模式與解法

模式一:全表掃描導致行鎖升級為表鎖

-- 沒有索引的 WHERE 條件
UPDATE t1 SET val=1 WHERE uid='xxxx';  -- uid 無索引 → 表鎖

解法:為 WHERE、JOIN、ORDER BY 欄位建立索引。

模式二:索引順序不一致

-- Session A
UPDATE t1 SET a=1 WHERE id=1;
UPDATE t1 SET b=2 WHERE id=2;

-- Session B(順序相反)
UPDATE t1 SET b=2 WHERE id=2;
UPDATE t1 SET a=1 WHERE id=1;

解法:應用層統一按主鍵順序存取多行資料。

模式三:IN 子查詢鎖範圍過大

DELETE FROM t1 WHERE id IN (SELECT id FROM t2 WHERE ...);

解法:改用 JOIN 或拆分為應用層分批處理。

配置優化建議

  • innodb_lock_wait_timeout:預設 50s,可縮短至 10-20s 快速失敗
  • innodb_deadlock_detect=ON:保持開啟(預設)
  • 長事務拆短、避免使用者互動中持有事務

總結檢查清單

  1. 是否有未加索引的更新/刪除?
  2. 多表更新順序是否固定?
  3. 事務是否過長?
  4. 隔離級別是否可降為 READ COMMITTED?
copyright © 萬盛學電腦網 all rights reserved