呈现的场景
- 业务上面临高并发解决,因为数据可能频繁进行写入与更新,因而应用的是 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 执行时,便会造成死锁
相干陈说性知识 & 官网文档 & 集体了解
- InnoDB Locking
- MySql 的锁