MySQL--死锁的产生和解除方法

一、死锁是怎么产生的?

  两个或多个事务在操作过程中,产生了多个锁,这些事务相互等待着对方释放锁,形成闭环阻塞,导致死锁。

举个例子

假如有如下订单记录表,只有这几条记录,其中 id 字段为主键索引,order_no 字段普通索引,也就是非唯一索引:

  假设这时有两个事务,一个事务要插入订单 1007 ,另外一个事务要插入订单 1008,因为需要对订单做幂等性校验,所以两个事务先要查询该订单是否存在,不存在才插入记录,过程如下:


  可以看到,两个事务都陷入了等待状态(前提没有打开死锁检测),也就是发生了死锁,因为都在相互等待对方释放锁。

具体是怎么发生的呢?

  首先,因为两条记录都不存在,事务A的当前读会产生一个间隙锁,然后事务B的当前读也产生了一个间隙锁(间隙锁是相互兼容的,可以同时存在),接着事务A想要插入一条记录,但是发现B事务加上了间隙锁,不能插入,于是产生一个插入意向锁,事务B也想要插入一条记录,但是发现A的间隙锁,于是也产生一个插入意向锁。就这样,两个事务互相等待对方释放间隙锁,从而形成死锁,阻塞线程。

如何解除死锁?

  在数据库层面,有两种策略通过「打破循环等待条件」来解除死锁状态:

1、设置事务等待锁的超时时间。

  当一个事务的等待时间超过该值后,就对这个事务进行回滚,于是锁就释放了,另一个事务就可以继续执行了。在 InnoDB 中,参数 innodb_1ock_wait_timeout 是用来设置超时时间的,默认值时 50 秒。
  当发生超时后,就出现下面这个提示:

ERROR 1205(HY000): Lock wait timeout exceeded; try restarting transaction

2、开启主动死锁检测。

  主动死锁检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将innodb_deadlock_detect参数设置为 on,表示开启这个逻辑,默认就开启。
  当检测到死锁后,就会出现下面这个提示:

ERROR 1213 (48001): Deadlock found when trying to get lock; try restarting transaction
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值