Mysql SELECT FOR UPDATE - 奇怪的问题

Mic*_*zyk 7 mysql locking blocking

我有一个奇怪的问题(至少对我来说:))与MySQL的锁定工具.

我有一张桌子:

create table `test` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  PRIMARY KEY (`id`)  
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)

有了这些数据:

+ ---- +
| id |
+ ---- +
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 10 |
| 11 |
| 12 |
+ ---- +

现在我有2个客户端在开头执行这些命令:

set autocommit = 0;
设置会话事务隔离级别可序列化;
开始;

现在最有趣的部分.第一个客户端执行此查询:(意图插入id等于9的行)

SELECT*from test where id = 9 FOR UPDATE;
空集(0.00秒)

然后第二个客户端做同样的事情:

SELECT*from test where id = 9 FOR UPDATE;
空集(0.00秒)

我的问题是:为什么第二个客户端没有阻止?应该由第一个查询设置独占间隙锁,因为已使用FOR UPDATE而第二个客户端应该阻止.

如果我错了,有人可以告诉我如何正确地做到这一点吗?

我使用的MySql版本是:5.1.37-1ubuntu5.1

nos*_*nos 3

因为那时,返回(空)结果是安全的 - 没有为 id=9 的记录设置锁定,因为该记录不存在,因此无法更新 - 我认为你不能依赖 innodb在这种情况下设置读锁。但它应该在 id=9 上设置写锁。

如果稍后某个事务确实更新了表,并与另一个事务接触了相同的数据,则更新可能会阻塞其中一个事务,并且如果另一个事务提交了该数据,则稍后会失败。在这种情况下,事务失败是完全正常的 - 让您自行处理 - 这通常是重试事务的问题。

如果有一条 id=9 的记录,您可能会看到 2.select块,直到第一个事务完成为止,因为现在有一条记录必须被读取锁定,以防第一个事务决定更新该行。