对于它的价值,这种锁定不限于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
...
正如您在记录的错误中所讨论的,错误 #67452 Setting a variable from a select 在使用 read uncommitted 时获取锁,这种行为可能是设计使然。它似乎SELECT
与其结果用于修改数据的语句属于同一类别,如下所述:
http://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html
当在结构中使用 SELECT 时REPLACE INTO t SELECT ... FROM s WHERE ...
,UPDATE t ... WHERE col IN (SELECT ... FROM s ...)
InnoDB 在 table 的行上设置共享的 next-key 锁s
。
使用 next-key locks 的原因是为了让SELECT
结果更稳定。也就是说,我们不希望与 匹配的行在SELECT
用于一个UPDATE
或其他数据修改语句时发生变化。
即使 tx_isolation 是REPEATABLE-READ
,这也很重要,因为 InnoDB 不支持REPEATABLE-READ
语句SELECT
作为任何类型的UPDATE
.
回复您的评论:
无论文档如何,都会发生以下情况:
当您执行普通SELECT
语句时,InnoDB 不会在任何事务隔离中锁定任何东西,除了SERIALIZABLE
.
如果您执行SELECT ... LOCK IN SHARE MODE
or SELECT ... FOR UPDATE
,它当然会锁定。
但是,当您SELECT
作为数据修改语句的一部分执行时,如INSERT INTO...SELECT
或在 a 的子查询中或在 a 中UPDATE
找到时SET @variable := (SELECT...)
,它使用共享锁来确保数据在更新过程中不会更改。
文档可能不完整。更好地测试。