| 鎖類型 | 語句 | 行為 | 兼容性 |
|---|---|---|---|
| 共享鎖 (S Lock / 讀鎖) | SELECT ... LOCK IN SHARE MODE | 允許並發讀、阻塞寫 | S-S 兼容,S-X 互斥 |
| 排他鎖 (X Lock / 寫鎖) | SELECT ... FOR UPDATE | 阻塞其他讀寫 (除非隔離級別允許一致性非鎖定讀) | X-X、X-S 互斥 |
BEGIN;
SELECT coin FROM user WHERE uid = 123 FOR UPDATE; -- 加排他鎖
UPDATE user SET coin = coin - 100 WHERE uid = 123;
INSERT INTO cash_log (uid, amount) VALUES (123, 100);
COMMIT; -- 或 ROLLBACK
破壞任一條件即可避免死鎖,最實用的是 破壞環路:統一加鎖順序。
-- 表結構
-- id PK, name IDX, age 普通列
-- Session A
UPDATE user SET name='x' WHERE name='y'; -- 走 name 索引 → 需回表鎖 PK
-- Session B
UPDATE user SET name='y' WHERE id=100; -- 走 PK 索引 → 需鎖 name 索引
-- 並發執行 → A 持有 name 鎖等 PK,B 持有 PK 鎖等 name → 死鎖
-- 改造 Session A
UPDATE user SET name='x' WHERE id = (SELECT id FROM user WHERE name='y'); -- 先走 PK
READ COMMITTED + innodb_locks_unsafe_for_binlog=1 (5.7 棄用) 可減少間隙鎖,但可能導致幻讀,需業務容忍。ER_LOCK_DEADLOCK (1213) 指數退避重試 2-3 次。SHOW ENGINE INNODB STATUS 定期抓取 LATEST DETECTED DEADLOCK 入庫分析熱點表/索引。innodb_lock_wait_timeout 默認 50s) 報 ER_LOCK_WAIT_TIMEOUT (1205)。1213。掌握加鎖順序統一、事務極小化、重試兜底三板斧,死鎖從「疑難雜症」變成「可控小概率事件」。