跳到主要内容

死锁复现与诊断

通过两个会话不同加锁顺序复现死锁,并解读 InnoDB 死锁日志。

准备

CREATE TABLE t (
id BIGINT PRIMARY KEY,
v INT,
KEY idx_v (v)
) ENGINE=InnoDB;
INSERT INTO t VALUES (1,1),(2,2);

复现

会话 A:

START TRANSACTION;
UPDATE t SET v = v + 1 WHERE id = 1;

会话 B:

START TRANSACTION;
UPDATE t SET v = v + 1 WHERE id = 2;

再交叉更新:

会话 A:

UPDATE t SET v = v + 1 WHERE id = 2; -- 等待 B

会话 B:

UPDATE t SET v = v + 1 WHERE id = 1; -- 形成环

InnoDB 将回滚代价较小的事务,报死锁错误。

诊断

SHOW ENGINE INNODB STATUS\G

关注:

  • WAITING/LOCK MODE 与索引记录范围(是否因为范围条件导致 Next-Key 锁)。
  • 检查 SQL 是否命中合适索引,避免锁住过多记录。

规避策略

  • 统一加锁顺序(按主键升序),避免环依赖。
  • 将范围更新拆批,缩小锁范围;或改精确命中索引。
  • 减少长事务,适度提高 innodb_lock_wait_timeout 并做好重试。