死锁

作者: 骁兵 | 来源:发表于2019-02-28 11:15 被阅读3次

      为了减少死锁的可能性,保持插入或更新数据的事务足够小,避免它们长时间保持打开状态;当不同的事务更新多个表或大范围的行时,在每个事务中使用相同的操作顺序;在 SELECT ... FOR UPDATE and UPDATE ... WHERE 语句上创建索引。

      当死锁检测被打开时(默认),InnoDB会检测条件并回滚其中一个事务,InnoDB会回滚较小的事务(insert、update、delete语句较少)。如果事务检测innodb_deadlock_detect被关闭时,InnoDB依赖innodb_lock_wait_timeout配置来回滚死锁事务。

      使用SHOW ENGINE INNODB STATUS 命令可以查看死锁。

    一个死锁的例子
    事务A执行以下语句,并获得S锁

    mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
    Query OK, 0 rows affected (1.07 sec)
    
    mysql> INSERT INTO t (i) VALUES(1);
    Query OK, 1 row affected (0.09 sec)
    
    mysql> START TRANSACTION;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT * FROM t WHERE i = 1 FOR SHARE;
    +------+
    | i    |
    +------+
    |    1 |
    +------+
    

    事务B执行以下语句,因为S锁被事务A持有,事务B等待获取X锁

    mysql> START TRANSACTION;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> DELETE FROM t WHERE i = 1;
    

    事务A再执行以下语句,因为事务B比事务A更早申请X锁,所以事务A等待事务B,最后发生发生死锁

    mysql> DELETE FROM t WHERE i = 1;
    ERROR 1213 (40001): Deadlock found when trying to get lock;
    try restarting transaction
    

    相关文章

      网友评论

        本文标题:死锁

        本文链接:https://www.haomeiwen.com/subject/inqhuqtx.html