mysql innodb的死锁问题

一、先了解下innodb锁机制,实现原理:

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁! 索引分为主键索引和二级索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了二级索引,MySQL会先锁定该二级索引,再锁定相关的主键索引。

然后innodb行锁分为以下情形:

1)Record lock :对索引项加锁,即锁定一条记录。
2)Gap lock:对索引项之间的‘间隙’、对第一条记录前的间隙或最后一条记录后的间隙加锁,即锁定一个范围的记录,不包含记录本身
3)Next-key Lock:锁定一个范围的记录并包含记录本身(上面两者的结合)。
4)insert intention lock(IK)
如果插入前,该间隙已经由gap锁,那么Insert会申请插入意向锁。因为了避免幻读,当其他事务持有该间隙的间隔锁,插入意向锁就会被阻塞。

注意:InnoDB默认级别是repeatable-read级别,所以下面说的都是在RR级别中的。

Next-Key Lock是行锁与间隙锁的组合,这样,当InnoDB扫描索引记录的时候,会首先对选中的索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。如果一个间隙被事务T1加了锁,其它事务是不能在这个间隙插入记录的

行锁防止别的事务修改或删除,GAP锁防止别的事务新增(防止新增包括insert和update已有数据到这个范围中),行锁和GAP锁结合形成的的Next-Key锁共同解决了RR级别在写数据时的部分幻读问题,一定注意只是部分幻读问题;

当当前索引是一个普通索引(即不一定唯一)的时候,会加一个gap lock来防止幻读,此gap lock 会锁住一个左开右闭的区间。假设索引为xx_idx(xx_id),数据分布为1,4,6,8,12,当更新xx_id=9的时候,这个时候gap lock的锁定记录区间就是(8,12],也就是锁住了xxid in (9,10,11,12)的数据,当有其他事务要插入xxid in (9,10,11,12)的数据时,就会处于等待获取锁的状态。

主键和唯一索引可以锁定一行,所以不需要间隙锁锁定。
如果列没有索引或者具有非唯一索引,该语句会锁定当前索引前的间隙。

二、举个死锁例子

在这里插入图片描述

事务A正在获取插入意向锁,持有排他gap锁
事务B正在获取插入意向锁

那么就可以推断出:事务A持有gap lock,等待事务B的insert intention lock释放;事务B持有gap lock,等待事务A的insert intention lock释放,从而导致死锁。

https://www.cnblogs.com/twoheads/p/10703023.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值