不管怎样,这个锁定不限于READ-UNCOMMITTED:
mysql1> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
mysql1> BEGIN;
mysql1> SET @x := (SELECT x FROM foo LIMIT 1);
mysql2> UPDATE foo SET x = x+1;
[gets a lock wait]
mysql3> SHOW ENGINE INNODB STATUS;
...
---TRANSACTION 228746, ACTIVE 22 sec
2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 58, OS thread handle 0x7fc262a1c700, query id 8163
192.168.56.1 root cleaning up
TABLE LOCK table `test`.`foo` trx id 228746 lock mode IS
RECORD LOCKS space id 801 page no 3 n bits 80 index `PRIMARY`
of table `test`.`foo` trx id 228746 lock mode S
...
正如您在记录的错误Bug #67452 Setting a variable from a select acquires a lock when using read uncommitted 中所讨论的,这种行为可能是设计使然。它似乎与 SELECT 语句属于同一类别,其结果用于修改数据,例如描述的这些案例:
http://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html
当在构造 REPLACE INTO t SELECT ... FROM s WHERE ... 或 UPDATE t ... WHERE col IN (SELECT ... FROM s ...) 中使用 SELECT 时,InnoDB 会对表 s 中的行设置共享的 next-key 锁。
next-key locks的原因是为了让SELECT的结果更稳定。也就是说,我们不希望SELECT 匹配的行在用于UPDATE 或其他数据修改语句时发生变化。
即使 tx_isolation 是 REPEATABLE-READ,这也很重要,因为当 SELECT 语句作为任何类型的 UPDATE 的一部分执行时,InnoDB 不支持 REPEATABLE-READ。
你的评论:
无论文档如何,都会发生以下情况:
当你执行普通的SELECT 语句时,InnoDB 不会锁定任何东西,除了SERIALIZABLE 之外的任何事务隔离。
如果您执行SELECT ... LOCK IN SHARE MODE 或SELECT ... FOR UPDATE,它当然会锁定。
但是,当您将 SELECT 作为数据修改语句的一部分(如 INSERT INTO...SELECT)或在 UPDATE 的子查询中或在 SET @variable := (SELECT...) 中找到时,它使用共享锁来确保更新过程中数据不会改变。
文档可能不完整。更好地测试。