mysql8 死锁_mysql8 参考手册--InnoDB中的死锁

死锁是指由于每个事务都持有对方需要的锁而无法进行其他事务的情况。因为这两个事务都在等待资源变得可用,所以两个都不会释放它持有的锁。

当事务锁定多个表中的行(通过诸如UPDATE或的 语句SELECT ... FOR UPDATE)但顺序相反时,可能会发生死锁 。当此类语句锁定索引记录和间隙的范围时,由于时序问题,每个事务都获得了一些锁而没有获得其他锁,也会发生死锁。有关死锁的示例,请参见 第15.7.5.1节“ InnoDB死锁示例”。

为了减少死锁的可能性,请使用事务而不是LOCK TABLES语句;保持插入或更新数据的事务足够小,以使其长时间不保持打开状态;当不同的事务更新多个表或大范围的行时,SELECT ... FOR UPDATE在每个事务中使用相同的操作顺序(例如 );在SELECT ... FOR UPDATE和 UPDATE ... WHERE 语句中使用的列上创建索引。死锁的可能性不受隔离级别的影响,因为隔离级别更改了读取操作的行为,而死锁则是由于写入操作而发生的。有关避免死锁状态并从死锁状态中恢复的更多信息,请参见 第15.7.5.3节“如何最小化和处理死锁”。

启用死锁检测(默认设置)并且发生死锁后,将InnoDB检测条件并回滚其中一个事务(受害方)。如果使用innodb_deadlock_detect 配置选项禁用了死锁检测,则 在死锁的情况下InnoDB依靠该 innodb_lock_wait_timeout设置回滚事务。因此,即使您的应用程序逻辑正确,您仍然必须处理必须重试事务的情况。要查看InnoDB用户事务中的最后一个死锁,请使用 SHOW ENGINE INNODB STATUS命令。如果频繁出现死锁,说明事务结构或应用程序错误处理存在问题,请使用 innodb_print_all_deadlocks 启用此设置可将有关所有死锁的信息打印到 mysqld错误日志中。

InnoDB死锁示例

以下示例说明了锁定请求将导致死锁时如何发生错误。该示例涉及两个客户端A和B。

首先,客户端A创建一个包含一行的表,然后开始事务。在事务中,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开始事务并尝试从表中删除该行:

mysql>START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql>DELETE FROM t WHERE i = 1;

删除操作需要一个X锁。无法授予该S锁,因为它与客户端A持有的锁不兼容 ,因此该请求进入针对行和客户端B块的锁请求队列中。

最后,客户端A还尝试从表中删除该行:

mysql> DELETE FROM t WHERE i = 1;

ERROR 1213 (40001): Deadlock found when trying to get lock;

try restarting transaction

此处发生死锁是因为客户端A需要 X锁才能删除该行。但是,不能授予该锁定请求,因为客户端B已经有一个X锁定请求,并且正在等待客户端A释放其S锁定。由于B事先要求锁,因此SA持有的锁也不能 升级 X为X锁。结果, InnoDB为其中一个客户端生成错误并释放其锁。客户端返回此错误:

ERROR 1213 (40001): Deadlock found when trying to get lock;

try restarting transaction

届时,可以授予对另一个客户端的锁定请求,并从表中删除该行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值