度小满面试:mysql插入会导致死锁吗?
会的,很多人以为只有更新的情况下才会造成死锁,比如下面2个事务同时执行形成了互相等待。其实插入也会。站长收到反馈头部金融类公司开发特别喜欢问这个问题。
事务一执行: UPDATE inventory SET stock = stock - 10 WHERE id = 1; UPDATE inventory SET stock = stock - 10 WHERE id = 2; 事务二执行 UPDATE inventory SET stock = stock - 10 WHERE id=2; UPDATE inventory SET stock = stock - 10 WHERE id = 1;
insert 唯一键冲突
我就先和你分享一个经典的死锁场景。
在 session A 执行 rollback 语句回滚的时候,session C 几乎同时发现死锁并返回。这个死锁产生的逻辑是这样的:
在 T1 时刻,启动 session A,并执行 insert 语句,此时在索引 c 的 c=5 上加了记录锁。注意,这个索引是唯一索引,因此退化为记录锁。
在 T2 时刻,session B 要执行相同的 insert 语句,发现了唯一键冲突,加上读锁;同样地,session C 也在索引 c 上,c=5 这一个记录上,加了读锁。
T3 时刻,session A 回滚。这时候,session B 和 session C 都试图继续执行插入操作,都要加上写锁。两个 session 都要等待对方的行锁,所以就出现了死锁。
这个流程的状态变化图如下所示。
如何避免?
1 关于insert造成死锁的情况,我之前做过测试,事务1并非只有insert,delete和update都可能造成死锁问题,核心还是插入唯一值冲突导致的.我们线上的处理办法是 1 去掉唯一值检测 2减少重复值的插入 3降低并发线程数量
#mysql##java##面试#