文档介绍:InnoDB死锁检测
1 Overview
    InnoDB自动检测死锁。如果死锁发生,那么InnoDB会回滚权重相对小的事务。实际上,InnoDB中存在以下两种类型的死锁:
真正的事务间循环等待。
在进行死锁检测的过程中,如果InnoDB认为检测的代价过大(例如需要递归检查超过200个事务等),那么InnoDB放弃死锁检测,并认为死锁发生。为解决200个事物的限制,可以对mysql源代码进行修改,#define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200
     本文中使用的MySQL版本: ,InnoDB plugin版本: 。
     其中为了检查当前事务发生的数目,可以参考 Innodb_row_lock_current_waits参数。
2 Scenarios
    如果死锁发生,除了应用程序的日志之外,最有价值的信息恐怕就是show innodb status的输出了,然而show innodb status的输出中死锁相关的信息并不完整(例如只记录导致死锁的最后两个事务,以及最后执行的两个SQL等)。    基于在日常工作中的经验,笔者总结了以下一定/可能会导致死锁的场景。
Scenario 1
    CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR(10)) ENGINE=InnoDB;
    INSERT INTO test VALUES(1, '1'), (2, '2');
    SET @***@tx_isolation = 'MITTED';
Session A
Session B
START TRANSACTION;
START TRANSACTION;
UPDATE test SET name = '11' WHERE id = 1;
 
 
UPDATE test SET name = '22' WHERE id = 2;
UPDATE test SET name ='21' WHERE id = 2;# BLOCKED
 
 
UPDATE test SET name = '12' WHERE id = 1;# DEADLOCK
    点评:这是最常见的死锁场景之一,解决方法就是resource ordering,即确保所有关联事务均以相同的顺序持有锁。
Scenario 2
    CREATE TABLE t (id INT PRIMARY KEY, count INT) ENGINE = InnoDB;
    INSERT INTO t VALUES(1, 1);
    SET @***@tx_isolation = 'MITTED';
Session A
Session B
START TRANSACTION;
START TRANSACTION;
SELECT * FROM t WHERE id = 1 LOCK IN SHARE MODE;
 
 
SELECT * FROM t WHERE id = 1 LOCK IN SHARE MODE;
UPDATE t SET