MySQL死锁专题
insert加锁
官网:
INSERT sets an exclusive lock on the inserted row. This lock is an index-record lock, not a next-key lock (that is, there is no gap lock) and does not prevent other sessions from inserting into the gap before the inserted row.Prior to inserting the row, a type of gap lock called an insertion intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.If a duplicate-key error occurs, a shared lock on the duplicate index record is set. This use of a shared lock can result in deadlock should there be multiple sessions trying to insert the same row if another session already has an exclusive lock.
网友翻译:
insert会对插入成功的行加上排它锁,这个排它锁是个记录锁,而非next-key锁(当然更不是gap锁了),不会阻止其他并发的事务往这条记录之前插入记录。在插入之前,会先在插入记录所在的间隙加上一个插入意向gap锁(简称I锁吧),并发的事务可以对同一个gap加I锁。如果insert 的事务出现了duplicate-key error ,事务会对duplicate index record加共享锁。这个共享锁在并发的情况下是会产生死锁的,比如有两个并发的insert都对要对同一条记录加共享锁,而此时这条记录又被其他事务加上了排它锁,排它锁的事务提交或者回滚后,两个并发的insert操作是会发生死锁的。
并发insert产生死锁案例:
死锁记录
知乎上对此说明:
https://zhuanlan.zhihu.com/p/351266632
避免死锁:
将大事务拆成小事务
添加合理的索引,走索引避免为每一行加锁,降低死锁的概率避免业务上的循环等待(如加分布式锁之类的)
降低事务隔离级别(如RR -> RC 当然不建议这么干)
并发插入时使用replace/on duplicate也可以避免死锁
锁监控及处理
参考:
https://www.cnblogs.com/klvchen/p/12076019.html
死锁日志
参考:
https://www.aneasystone.com/archives/2018/04/solving-dead-locks-four.html