mysql锁-记一次innodb死锁分析

前言:
最近项目上压测出现了数据库死锁情况,经过一番排查,最终定位在updateData方法上

分析该方法:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public int udpateData(DataTrace trace){
	//根据索引更新数据,该子方法也加了@Transactional注解,使用默认事务机制:required
	updateOtherByIndex(trac);
	//根据主键更新数据
	updateOtherByPrimary(trac);
}

1.该方法执行了两个更新sql,一个根据索引,一个根据主键
2.外层调用udpateData方法,存在这种情况:首先异步调用,然后马上同步调用

分析死锁原因:

1.首先udpateData方法存在事务嵌套,子方法updateOtherByIndex使用默认事务机制required,会将已存在的事务加入当前事务中,所以两个更新sql是在一个事务中
2.既然没有开启一个新事务,则两个更新sql在一个事务中,并发调用udpateData方法就可能会出现问题(而且也是巧,第一个请求不会调用子方法updateOtherByIndex):
第一个进来事务会执行updateOtherByPrimary方法,获取主键锁
第二个进行事务会执行updateOtherByIndex方法,获取索引锁,然后执行updateOtherByPrimary方法,获取主键锁
这种循环情况下在压测环境很容易出现死锁了…

虽然原因找到了,不过为了更好地理解和加深学习,我本地做了一个死锁测试:
一、前置条件:

1.创建表:

CREATE TABLE `test_deadlock_table` (
  `primary_no` char(16) NOT NULL COMMENT '主键号',
  `index_no` char(16) NOT NULL COMMENT '索引号',
  `status` tinyint(4) unsigned NOT NULL COMMENT '状态',
  PRIMARY KEY (`primary_no`),
  UNIQUE KEY `uk_index_no` (`index_no`) USING BTREE
) EN
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值