我有一个奇怪的问题(至少对我来说:))与MySQL的锁定工具。
我有一张桌子:
create table `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1
有了这些数据:
+ ---- +
| id |
+ ---- +
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 10 |
| 11 |
| 12 |
+ ---- +
现在我有2个客户端在开头执行这些命令:
设置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
答案 0 :(得分:3)
因为在那个时候,返回(空)结果是安全的 - 没有锁定为id = 9的记录设置,因为它不存在因此无法更新 - 我认为你不能在这种情况下依靠innodb设置读锁。它应该在id = 9上设置写锁定。
如果稍后,其中一个事务确实更新了表,并触摸与另一个事务相同的数据 - 更新可能会在其中一个事务中阻塞,如果另一个事务提交该数据,则稍后会失败。在这样的情况下交易失败是完全正常的 - 让你去处理它 - 这通常是重试交易的问题。
如果有一个id = 9的记录,你可能会看到2. select
块,直到第一个事务完成,因为现在有一个记录必须被锁定以防第一个事务决定更新该行。
答案 1 :(得分:-1)