出现的场景
- 业务上需要并发处理,且数据根据业务属性保持唯一(如每天每个商家每个门店一条数据),由于数据可能频繁进行写入与更新,因此使用的是insert on duplicate key update语句,在高并发场景下,导致死锁报错
原因分析
- 死锁的本质是多个事务等待对方所持有的资源释放,且不会释放自身所持有的资源,导致事务之间循环等待
- 通过查阅文档以及数据库分析,在on duplicate key时,会在前一个索引值到当前值加临键锁,而多个事务互相等待对方的锁释放,是造成死锁的原因
- lock_mode X locks gap before rec insert intention waiting
举例说明
在以下结构中,value字段存在唯一索引
事务A
// step1 执行到此处时,由于value=3已存在,此时会对(1,3]加临键锁
insert into table(value) values(3) on duplicate key update value = 7;
// step3 执行到此处时,由于3~5的区间已被锁住,需要等待事务2释放临键锁
insert into table(value) values(4) on duplicate key update value = 7;
事务B
// step2 执行到此处时,由于value=5已存在,此时会对(3,5]加临键锁
insert into table(value) values(5) on duplicate key update value = 8;
// step4 执行到此处时,由于1~3的区间已被锁住,需要等待事务1释放临键锁
insert into table(value) values(2) on duplicate key update value = 8;
当执行顺序按照step1~step4执行时,便会形成死锁
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。