MySQL Update批量更新死锁问题排查

MySQL Update批量更新死锁问题排查

背景

业务中有两个不同的业务,更新同一批数据时出现死锁问题,sql语句如下

update test set a= 1 where name = 'test';
update test set b = 2 where name = 'test' and time >0;
-- 这里的name是一个普通的索引

频繁出现死锁

锁分析

update锁的执行过程:

  1. 首先根据where条件查出符合条件的数据,这个查询是一条一条查询的
  2. Innodb引擎支持行锁,才会出现死锁,表锁不会出现死锁
  3. MySQL会首先取出来第一条符合的数据,并同时对这个数据加上共享锁
  4. 然后再对这个数据进行S锁升级到X锁

数据加锁的过程(如果sql没有用到索引,会加表锁):

  1. 首先查询这个数据的索引,如果是非主键索引,那么会先给索引加锁
  2. 然后会根据索引查找对应的主键,进行主键聚簇索引加锁

可能性分析

  1. 增加time条件导致的加锁异常
    我首先猜测,是不是因为第二条sql语句中加了一个非索引条件,导致索引加锁顺序发生变化,先对主键索引进行加锁,然后再对普通索引进行加锁,后来查询资料,说加锁顺序是一定的,一定是先加普通索引的锁,所以这个排除了
  2. 多线程并发问题导致S锁异常
    两个事务同时对一条数据进行更新的时候(这个是否为并发有待验证),两个update语句都拿到了数据的S锁,但是升级X锁的时候,出现问题,因为S锁升级X锁,在隔离等级是RC的情况下,了解到必须等所有的S锁解开,才能S锁升X锁,所以两个事务相互等待,死锁了。

经过分析,第二种可能性更大,但是系统是频繁报错,所以后续还会继续排查

结果处理

MySQL之上加了一层redis缓存锁,防止多个脚本同时更新一个数据,如果有其他的解决方法,希望大家评论回复下

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Michael·Ren

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值