Для того, что это стоит, эта блокировка не ограничена 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 Установка переменной из select приобретает блокировка при использовании read uncommitted , это поведение, вероятно, по дизайну. Кажется, что она относится к той же категории, что и SELECT
, результаты которой используются для изменения данных, как описано выше:
http://dev.mysql.com/doc/refman/ 5.6 / ru / innodb-locks-set.html
Когда в конструкциях
blockquote>REPLACE INTO t SELECT ... FROM s WHERE ...
илиUPDATE t ... WHERE col IN (SELECT ... FROM s ...)
используется SELECT, InnoDB устанавливает общие блокировки следующих клавиш в строках из таблицыs
.Причина блокировки следующей клавиши - сделать результаты
SELECT
более стабильными. То есть мы не хотим, чтобы строки, сопоставляемыеSELECT
, менялись, когда они используются дляUPDATE
или другого оператора, изменяющего данные.Даже если tx_isolation
REPEATABLE-READ
, это важно, потому что InnoDB не поддерживаетREPEATABLE-READ
для операторовSELECT
, когда они выполняются как часть любого типаUPDATE
.. Ваш комментарий:
Независимо от документации, вот что происходит:
Когда вы выполняете простой оператор
SELECT
, InnoDB ничего не блокирует в любой изоляции транзакции, кромеSERIALIZABLE
.Если вы выполняете
SELECT ... LOCK IN SHARE MODE
илиSELECT ... FOR UPDATE
, он блокируется, конечно.Но когда вы выполняете
SELECT
как часть инструкции, изменяющей данные, напримерINSERT INTO...SELECT
или в подзапросеUPDATE
или, как вы обнаружили вSET @variable := (SELECT...)
, он использует общую блокировку, чтобы убедиться, что данные не изменяются во время обновления.Документация может быть неполный. Лучше проверить.