MySQL锁(3):死锁

死锁概念

死锁是指两个及以上的事务在执行过程中因争锁造成的相互等待。

解决死锁一般有两种方法,

  • 设置超时时间:两个事务等待过程实际上是阻塞过程,对参数innodb_lock_wait_timeout进行设定来设置超时时间。
  • wait-for graph检验死锁,一旦发现存在死锁,则对死锁中的事务进行回滚。

死锁的解决

1)设置超时时间

前者的优势是简单,一旦两个事务出现死锁的情况,其中一个事务先到达设定的阈值后,该事务进行回滚,另一个事务可以继续执行。

但是这种方法也存在弊端,设置超时时间的方式可以看做是FIFO的顺序进行回滚,如果超时事务的操作很多,使用undo log进行回滚时的消耗可能比未超时的事务要大得多。

2)wait-for graph

wait-for graph可用于进行死锁检测,该方法也是InnoDB使用的死锁解决方法。wait-for graph保存两种信息,

  • 锁的信息链表
  • 事务等待链表

通过上述两个链表可以构造出一张图,如果图中存在回路,说明存在死锁。

wait-for graph中,图中的节点是事务,对节点之间边的定义如下,

  • 事务T1等待事务T2释放锁
  • 事务T1发生在事务T2之后

以下图为例,
在这里插入图片描述
上图包含的信息如下,

  • transaction wait lists中存在4个事务,所以在wait-for graph中也会有四个节点。
  • Lock lists中,
    事务t2对记录row1使用了X lock锁定该行数据。
    事务t1对记录row2使用了S Lock锁定该行数据。
    事务t1和t2的锁不兼容,所以t1在等待事务t2释放row1上的锁,故存在一条从t1指向t2的边
    事务t2的X lock与任何锁都不兼容,所以t2在等待事务t1和t4释放记录row2上的锁,故存在从t2指向t1和t4的边

由此得到如下wait-for graph,
在这里插入图片描述
图中可以发现节点t1和t2直接存在回路,故这两个节点对应的事务存在死锁。

wait-for graph是主动监测死锁的机制,通常采用深度优先算法实现。一旦发现存在死锁,在两个事务中选择undo成本低的事务进行回滚

死锁示例

死锁只存在于并发的情况,常见的死锁有两种。

1)AB-BA死锁

引发该类型死锁的原因是两个事务之间相互等待,

在这里插入图片描述
InnoDB默认大部分异常发生时不会回滚,但是死锁除外。发现死锁后,InnoDB会马上回滚undo成本低的事务。

2)特殊死锁

当前事务持有待插入记录的下一个记录的X锁,等待队列中存在一个S锁的请求,此时可能发生死锁。

create table t(
	a int primary key;
)engine=InnoDB;

insert into t values(1), (2), (3), (4), (5);

在这里插入图片描述
上面的操作中,会话A已经持有记录4的X锁,会话A在插入记录3时,发生了死锁的情况。

会话B在会话A获取了记录4的X锁后,请求记录4的S锁,但是由于X锁的不兼容性,导致会话A的事务陷入阻塞。但是会话A此时已经争取到了记录1和2的S锁

如果会话A的insert语句执行成功,会话B在获取到记录4的S锁后,还需要回过头去争取记录3的S锁。此时显得不合理,故InnoDB主动选择了死锁,并且回滚undo成本较高的事务,这一点与AB-BA死锁处理有差异。

降低死锁发生概率

  1. 更新数据时,where子句的条件字段尽量使用索引字段
  2. 使用索引字段时,尽量使用主键或唯一索引更新数据
  3. 减少非主键、非唯一索引上的范围更新
  4. 尽可能在事务中一次性锁定所有需要的数据行
  5. 对隔离性要求没那么严格时,将RR级别调整为RC级别,因为RR级别的间隙锁可能导致死锁

分析死锁的方法

实际工作中,死锁很难完全避免。捕获并处理死锁是编程时必要的。

InnoDB中使用show engine innodb status\G;可以查看最后一个死锁的信息,
image
此外设置innodb_print_all_deadlocks=on可以在error log中记录全部死锁信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值