呈现的场景
- 业务上面临高并发解决,因为数据可能频繁进行写入与更新,因而应用的是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的锁