一次mysql死锁问题的分析

本文深入探讨了一个由唯一键冲突引起的经典死锁问题,详细解释了死锁产生的逻辑,以及InnoDB如何通过共享锁、排他锁、意向锁和行锁等机制来管理并发事务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先问题始于生产环境的一批报错

### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
### The error may involve com.pdd.service.quebec.repository.repository.mapper.store.MerchantLogMapper.insertSelective-Inline
### The error occurred while setting parameters

从上面的异常信息可以看到是:merchant_log insert操作在事务回滚的时候,由于在尝试获取锁的时候发生了死锁,导致了异常。

一个经典的insert死锁问题

查了资料发现这个问题是一个经典的死锁问题,是一个因为唯一键冲突导致的死锁场景。

 

这个死锁产生的逻辑如下:

1. 在 T1 时刻,启动 session A,并执行 insert 语句,此时在索引 c 的 c=5 上加了排他记录锁。

2. 在 T2 时刻,session B 和 session C 要执行相同的 insert 语句,请求排他插入意向锁;但由于发生重复唯一键冲突,各自请求的排他记录锁转成共享记录锁。session B 和 session C 都在索引 c 上,c=5 这一个记录上加了读锁。

3. 在 T3 时刻,session A 回滚,释放索引c=5上的排他记录锁。这时候,session B 和 session C 都试图继续执行插入操作,都要请求索引c=5上的排他记录锁。由于X锁与S锁互斥,T2和T3都等待对方释放S锁。于是,死锁便产生了。

如果此场景下,只有两个事务T1与T2或者T1与T3,则不会引发如上死锁情况产生。

/---------------------------------------------------------------------------------------------------------/

                                               InnoDB的锁类型

1 基本锁: 共享锁(Shared Locks:S锁)与排他锁(Exclusive Locks:X锁)

mysql允许拿到S锁的事务读一行,允许拿到X锁的事务更新或删除一行。
加了S锁的记录,允许其他事务再加S锁,不允许其他事务再加X锁;
加了X锁的记录,不允许其他事务再加S锁或者X锁。

2. 意向锁(Intention Locks) 

InnoDB为了支持多粒度(表锁与行锁)的锁并存,引入意向锁。
意向锁是表级锁,可分为意向共享锁(IS锁)和意向排他锁(IX锁)。

事务在请求S锁和X锁前,需要先获得对应的IS、IX锁。

意向锁产生的主要目的是为了处理行锁和表锁之间的冲突,用于表明“某个事务正在某一行上持有了锁,或者准备去持有锁”。

3. 行锁

记录锁(Record Locks) 仅仅锁住索引记录的一行。

间隙锁(Gap Locks) 在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。

Next-Key Locks record lock + gap lock, 左开右闭区间。

插入意向锁(Insert Intention Locks) 

Gap Lock中存在一种插入意向锁(Insert Intention Lock),在insert操作时产生。在多事务同时写入不同数据至同一索引间隙的时候,并不需要等待其他事务完成,不会发生锁等待。
...

/---------------------------------------------------------------------------------------------------------/

问题重现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值