We have a table in MySQL using InnoDB, and we are using a transaction isolation level of read uncommitted. Why does setting @x
as shown acquire a lock?
mysql> set @x = (select userID from users limit 1);
Query OK, 0 rows affected (0.02 sec)
mysql>
Trying to update this table from another prompt results in a timeout error:
mysql> update users set userID = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
For what it's worth, this locking is not limited to
READ-UNCOMMITTED
:As discussed in the bug you logged, Bug #67452 Setting a variable from a select acquires a lock when using read uncommitted, this behavior is probably by design. It seems to fall into the same category as
SELECT
statements whose results are used to modify data, like these cases described:http://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html
The reason for next-key locks is to make the
SELECT
results more stable. That is, we don't want the rows matched by theSELECT
to change while they are being used for anUPDATE
or other data-modifying statement.Even when the tx_isolation is
REPEATABLE-READ
, this is important because InnoDB doesn't supportREPEATABLE-READ
forSELECT
statements when they're executed as part of any type ofUPDATE
.Re your comment:
Regardless of the documentation, here's what happens:
When you do plain
SELECT
statement, InnoDB does not lock anything, in any transaction isolation exceptSERIALIZABLE
.If you do a
SELECT ... LOCK IN SHARE MODE
orSELECT ... FOR UPDATE
, it locks of course.But when you do
SELECT
as part of a data-modifying statement likeINSERT INTO...SELECT
or in a subquery of anUPDATE
or as you found in aSET @variable := (SELECT...)
, it uses a shared lock to make sure the data doesn't change while the update is in progress.Documentation can be incomplete. Better to test.