主表 A、子表 B(含 A 的 PK 做 FK)。插入先鎖 A 再鎖 B,刪除先鎖 B 再鎖 A → 交叉等待 → 死鎖。本文分析三種解決方案優缺點:移除 FK、預先轉向 FK、CASCADE 刪除。
-- 插入交易 (Tx1)
LOCK A (X) → 需 LOCK B (X) → 等待
-- 刪除交易 (Tx2)
LOCK B (X) → 需 LOCK A (X) → 等待
-- 結果:Tx1 持有 A 等 B,Tx2 持有 B 等 A → 死鎖
ALTER TABLE B DROP FOREIGN KEY fk_b_aid=0, name='DELETED',永不刪除UPDATE B SET a_id=0 WHERE a_id=要刪除的idFOREIGN KEY (a_id) REFERENCES A(id) ON DELETE CASCADEDELETE FROM A WHERE id=... 即可,B 表關聯行自動刪除| 方案 | 死鎖解決 | 參考完整性 | 實作複雜度 | 效能影響 | 推薦度 |
|---|---|---|---|---|---|
| 移除 FK | ✅ | ❌ | 低 | 無 | ⭐ |
| 預先轉向 | ✅ | ✅ | 高 | 額外 UPDATE | ⭐⭐ |
| CASCADE | ✅ | ✅ | 低 | 級聯開銷 | ⭐⭐⭐⭐⭐ |
innodb_lock_wait_timeout 避免無限等待innodb_deadlock_detect=ON(預設開啟)自動偵測犧牲者