Bug #60437 | InnoDB locking on consistent read in UPDATE ... SELECT statement | ||
---|---|---|---|
Submitted: | 11 Mar 2011 23:03 | Modified: | 8 Feb 2012 23:58 |
Reporter: | Roman Kravcenko | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Documentation | Severity: | S3 (Non-critical) |
Version: | 5.5.9 | OS: | Linux |
Assigned to: | John Russell | CPU Architecture: | Any |
[11 Mar 2011 23:03]
Roman Kravcenko
[11 Mar 2011 23:24]
Roman Kravcenko
In our case, this results in constant deadlocks if we try to update t2 at the same time.
[12 Mar 2011 5:10]
Valeriy Kravchuk
While our manual, http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html, indeed does not describe this specific case of UPDATE ... WHERE col in (SELECT ...), the same logic as for REPLACE applies: "For REPLACE INTO T SELECT ... FROM S WHERE ..., InnoDB sets shared next-key locks on rows from S." This is needed for correct binary logging and replication: "If the transaction isolation level is READ COMMITTED or innodb_locks_unsafe_for_binlog is enabled, and the transaction isolation level is not SERIALIZABLE, InnoDB does the search on S as a consistent read (no locks). Otherwise, InnoDB sets shared next-key locks on rows from S. InnoDB has to set locks in the latter case: In roll-forward recovery from a backup, every SQL statement must be executed in exactly the same way it was done originally." We see these S locks in your case, this is intended behavior for the reasons described above. At best I see a documentation request to include your specific case of UPDATE (or DELETE) with subquery into the manual.
[12 Mar 2011 10:35]
Roman Kravcenko
Thanks for clarification. I think I missed "REPLACE INTO T SELECT ... FROM S WHERE ..." part. Also http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html, states the following: InnoDB uses a consistent read for select in clauses like INSERT INTO ... SELECT, UPDATE ... (SELECT), and CREATE TABLE ... SELECT that do not specify FOR UPDATE or LOCK IN SHARE MODE if the innodb_locks_unsafe_for_binlog option is set and the isolation level of the transaction is not set to SERIALIZABLE. Thus, no locks are set on rows read from the selected table. Otherwise, InnoDB uses stronger locks and the SELECT part acts like READ COMMITTED, where each consistent read, even within the same transaction, sets and reads its own fresh snapshot. I think I missed the point in the "Otherwise ... SELECT part acts like READ COMMITTED" part too. If the documentation could be improved, it'll definitely help. Locking and transactions part are pretty hard one to understand. Thank you for support.
[12 Mar 2011 12:43]
Valeriy Kravchuk
I agree that http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html (and similar pages for older versions) needs clarification for the case of UPDATE ... (SELECT ...).
[8 Feb 2012 23:58]
John Russell
Updated the wording in 5.1, 5.5, and 5.6 manuals for both locations mentioned in this bug: The type of read varies for selects in clauses like INSERT INTO ... SELECT, UPDATE ... (SELECT), and CREATE TABLE ... SELECT that do not specify FOR UPDATE or LOCK IN SHARE MODE: * By default, InnoDB uses stronger locks and the SELECT part acts like READ COMMITTED, where each consistent read, even within the same transaction, sets and reads its own fresh snapshot. * To use a consistent read in such cases, enable the innodb_locks_unsafe_for_binlog option and set the isolation level of the transaction to READ UNCOMMITTED, READ COMMITTED, or REPEATABLE READ (that is, anything other than SERIALIZABLE). In this case, no locks are set on rows read from the selected table. --- When a SELECT is used in the constructs REPLACE INTO t SELECT ... FROM s WHERE ... or UPDATE t ... WHERE col IN (SELECT ... FROM s ...), InnoDB sets shared next-key locks on rows from table s.