出现的场景

  • 业务上需要并发处理,且数据根据业务属性保持唯一(如每天每个商家每个门店一条数据),由于数据可能频繁进行写入与更新,因此使用的是insert on duplicate key update语句,在高并发场景下,导致死锁报错

原因分析

  • 死锁的本质是多个事务等待对方所持有的资源释放,且不会释放自身所持有的资源,导致事务之间循环等待
  • 通过查阅文档以及数据库分析,在on duplicate key时,会在前一个索引值到当前值加临键锁,而多个事务互相等待对方的锁释放,是造成死锁的原因
  • lock_mode X locks gap before rec insert intention waiting

举例说明

在以下结构中,value字段存在唯一索引
image.png
事务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执行时,便会形成死锁

相关陈述性知识 & 官方文档 & 个人理解


老污的猫
30 声望5 粉丝