SELECT … FOR UPDATE 对不存在的行
Posted
技术标签:
【中文标题】SELECT … FOR UPDATE 对不存在的行【英文标题】:SELECT … FOR UPDATE on non-existent rows 【发布时间】:2020-07-15 04:13:14 【问题描述】:当“选择...更新不存在的行”时,我对锁感兴趣; 目前,'test02'表中的数据如下:
身份证
1
3
8
15
20
列id为主键;
当我跑步时:
会话 1: 开始交易; select * from test02 where id = 7 for update;
然后我打开另一个会话,并作为伙伴运行:
会话2: 开始交易; select * from test02 where id = 7 for update;
正如我所料,session2 将等待间隙锁 (3, 8);但是两个会话正常运行。有没有人可以帮助解释为什么 session2 不等待?
但是当我在 session3 中运行以下 sql 时:插入 test02(id) 值 (7);会话被阻塞,这意味着使用了 session1 中的间隙锁。但是我不明白为什么session2可以正常运行。
mysql 5.7 和 5.8 都显示相同的结果。
【问题讨论】:
但是当我在 session3 中运行以下 sql 时:插入 test02(id) 值 (7);会话被阻塞,这意味着使用了 session1 中的间隙锁。但我不明白 session2 在哪里可以正常运行。 请编辑您的问题以包含您在上面的评论。该评论与问题本身相关,可能会被前来回答的人忽略。 【参考方案1】:来自MySql documentation(8.0版):
这里还值得注意的是,冲突锁可以在一个 不同交易的差距。例如,交易 A 可以持有 当事务 B 持有一个间隙时,在间隙上共享间隙锁(间隙 S 锁) 同一个间隙上的排他间隙锁(gap X-lock)。原因 允许冲突的间隙锁是,如果一条记录被清除 一个索引,不同事务在记录上持有的间隙锁 必须合并。
InnoDB 中的间隙锁是“纯粹的抑制性”,这意味着它们的 唯一的目的是防止其他事务插入到 差距。间隙锁可以共存。一个事务采取的间隙锁确实 不阻止另一个事务对同一个事务进行间隙锁 差距。共享和独占间隙锁之间没有区别。 它们彼此不冲突,并且执行相同 功能。
在您的示例中,会话 2 不会等待会话 1,因为这正是 MySQL 中间隙锁的工作方式。否则就是期望与产品文档相矛盾的行为。
【讨论】:
以上是关于SELECT … FOR UPDATE 对不存在的行的主要内容,如果未能解决你的问题,请参考以下文章
当行不存在时,“SELECT FOR UPDATE”是不是会阻止其他连接插入?