Mysql InnoDB表已锁定但我可以从另一个会话中“选择”。是什么赋予了?

时间:2011-09-14 19:38:20

标签: mysql locking innodb

在我开发一些代码的过程中,我需要'写锁'一个InnoDB表,以避免竞争条件的并发问题。 'read lock'不够好,因为一些将“读取”锁定表(由其他会话锁定)的并行会话将获得错误数据,因为一旦锁定会话完成其工作,它读取的内容可能会蒸发(删除)。

到目前为止我需要'写锁'。欢迎提出意见,但只需要很长时间来解释为什么(对我的谦虚心态)除了完整的终端锁定之外我什么都看不到。

现在,对于我的测试,我已经打开了两个mysql命令行会话,两个都是常规用户(没有root或类似)。在一次会议中,我做了: 锁表mytable写; 结果确定(好吧,0行受影响......) 在第二个命令行会话中,我连接到同一个DB并在同一个表上运行一个简单的select *。令我惊讶的是,我得到了完整的答复。 在实际Web应用程序的更多测试中,我注意到在涉及Web应用程序的某些用例(具有持久连接属性的PHP + PDO)上,命令行或Web mysql连接确实阻塞,直到锁被释放但我没有识别究竟是什么导致了这种(期望的)效果,它还涉及不同的环境(PHP + PDO详细和命令行与2个命令行会话)。

我的问题是:为什么?为什么第二个命令行会话,在写锁定表上运行简单的'select'会被阻塞?

这是否与基于行的InnoDB锁的性质有关?如果是这样,这究竟是如何相关的? 如何我在InnoDB表上实现了这么简单的锁。我知道我可以创建一个'信号量'MyIsam表,除了充当“交通信号灯”之外没有其他目的,但会失去数据库级别保护的效果,并且会在应用程序中完成所有保护(或者错误地完成)水平。

TIA!

MySQL版本是5.1.54(Ubuntu 11.04)。

1 个答案:

答案 0 :(得分:2)

虽然InnoDB具有行级锁定,但它也具有多版本并发控制http://en.wikipedia.org/wiki/Multiversion_concurrency_control,因此这意味着读者不需要被编写者阻止。他们只能看到当前版本的记录。 (技术实现,在更新行时进行了修改,之前的版本将写入撤消旧事务的空间。)

如果要创建写锁定块读取器,则需要将SELECT更改为FOR UPDATE(即SELECT * FROM my_table WHERE cola = n FOR UPDATE)。