【发布时间】:2020-12-11 12:18:52
【问题描述】:
问题描述:
在mysql 8.0中,我启动一个事务并执行SELECT * FROM child WHERE id > 1000 FOR UPDATE;(事务一),然后我启动另一个事务并执行update child set id = id+10 where id = 101;(事务二),表child中有一行id = 101 ,但是这个事务二被阻止了。
如果我执行update child set id = id+10 where id = 102;(事务三)并且表中没有id = 102的行,事务三不会被阻塞,可以成功执行。
据我所知,mysql 8.0 gap lock只会锁定id大于1000的行,但是在第二个事务中,row id是101且不大于1000,所以两个事务不会相互冲突。那么为什么事务二会被事务一阻塞呢?
其他详情如下:
- 表
child结构:
CREATE TABLE `child` (\n `id` int NOT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
- 表
child中的所有数据:
mysql root@localhost:test> select * from child;
+------+
| id |
+------+
| 90 |
| 101 |
| 105 |
| 106 |
| 109 |
| 111 |
| 1007 |
+------+
7 rows in set
- 所有 mysql 8.0 配置均为默认配置。
- 这两个事务是并行的。
【问题讨论】:
-
然后我开始了另一个事务这个事务是并行的还是嵌套的?
-
锁定行为将取决于您的数据,因此请添加有关它的详细信息。具体来说:您的表中是否有一个位于间隙中的 id(例如从 112 到 1001 的值)?如果不是,则该行为是预期的。 (如果您仍然想知道原因,我们可以详细说明,但需要确认您的数据)。
-
我在上面添加了必要的细节,非常感谢您的回答。
-
当您将 101 更新为 111 时,表中的第 111 行会导致您违反主键,但是,您的示例数据证实了我关于间隙锁覆盖区域的一般假设更新将放置行。