SELECT FOR UPDATE 死锁分析(select for update锁表)

SELECT FOR UPDATE 死锁分析(select for update锁表)

编程文章jaq1232025-04-28 22:00:0613A+A-

工作中常用的业务场景:加锁获取,有则更新,无则插入。

表定义:

CREATE TABLE number (

prefix VARCHAR(20) NOT NULL DEFAULT '' COMMENT '前缀码',

value BIGINT NOT NULL DEFAULT 0 COMMENT '流水号',

UNIQUE KEY uk_prefix(prefix)

);

业务逻辑:

@Transactional

long acquire(String prefix) {

SerialNumber current = dao.selectAndLock(prefix);

if (current == null) {

dao.insert(new Record(prefix, 1));

return 1;

}

else {

current.number++;

dao.update(current);

return current.number;

}

}

MySQL InnoDB中在Repeatable Read的隔离级别下,当通过select for update的where条件筛出记录时,上面的代码是不会有deadlock问题的。然而当select for update中的where条件无法筛选出记录时,这时在有多个线程执行上面的acquire方法时是可能会出现死锁的。

场景复现和分析

  • 场景复现

初始化表

insert into number select 'bbb',2;

insert into number select 'hhh',8;

insert into number select 'yyy',25;

2个事务按照时序执行如下语句:

session 1

session 2

begin;



begin;

select * from number where prefix='ddd' for update



select * from number where prefix='fff' for update

insert into number select 'ddd',1


锁等待中

insert into number select 'fff',1

锁等待解除

死锁,session 2的事务被回滚


  • 死锁分析

1、session1 执行select for update

session1获得('bbb', 'hhh')的gap锁

2、session2 执行select for update

session2也获得('bbb', 'hhh')的gap锁

截自InnoDB的lock_rec_has_to_wait方法实现,可以看到的LOCK_GAP类型的锁只要不带有插入意向标识,不必等待其它锁(表锁除外)

3、session1尝试insert

session1尝试insert 'ddd',1时,由于发现session2已经获取了这个区间的gap锁,所以Innodb会给session1事务添加插入意向锁,锁的模式为LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,等待session2释放gap锁

4、session2尝试insert

由于session2在插入时也发现了session1的gap锁,同样加上了插入意向锁,等待session1释放掉gap锁。因此出现死锁的情况。

  • 死锁原因

两个session同时通过select for update,并且未命中任何记录的情况下,是有可能得到相同gap的锁的(要看where筛选条件是否落在同一个区间。如果上面的案例如果一个session准备插入'ddd'另一个准备插入'kkk'则不会出现冲突,因为不是同一个gap)。此时再进行并发插入,其中一个会进入锁等待,待第二个session进行插入时,会出现死锁。MySQL会根据事务权重选择一个事务进行回滚。

  • 避免死锁

1、事务隔离级别降低到RC,不存在gap锁

2、业务代码捕获异常进行重试

3、RR级别下,不同的where条件(不同的gap锁)则不会存在该问题

引用自:
https://www.cnblogs.com/micrari/p/8029710.html

点击这里复制本文地址 以上内容由jaq123整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

苍茫编程网 © All Rights Reserved.  蜀ICP备2024111239号-21