The world's most popular open source database
A locking read, an UPDATE, or a
DELETE generally set record locks
on every index record that is scanned in the processing of the
SQL statement. It does not matter whether there are
WHERE conditions in the statement that would
exclude the row. InnoDB does not remember the
exact WHERE condition, but only knows which
index ranges were scanned. The record locks are normally
next-key locks that also block inserts into the
“gap” immediately before the record.
If the locks to be set are exclusive, InnoDB
also retrieves the clustered index record and sets a lock on it.
If you have no indexes suitable for your statement and MySQL must scan the whole table to process the statement, every row of the table becomes locked, which in turn blocks all inserts by other users to the table. It is important to create good indexes so that your queries do not unnecessarily need to scan many rows.
For SELECT ... FOR UPDATE or SELECT
... IN SHARE MODE, locks are acquired for scanned
rows, and expected to be released for rows that do not qualify
for inclusion in the result set (for example, if they do not
meet the criteria given in the WHERE clause).
However, in some cases, rows might not be unlocked immediately
because the relationship between a result row and its original
source is lost during query execution. For example, in a
UNION, scanned (and locked) rows from a table
might be inserted into a temporary table before evaluation
whether they qualify for the result set. In this circumstance,
the relationship of the rows in the temporary table to the rows
in the original table is lost and the latter rows are not
unlocked until the end of query execution.
InnoDB sets specific types of locks as
follows:
SELECT ... FROM is a consistent read,
reading a snapshot of the database and setting no locks
unless the transaction isolation level is set to
SERIALIZABLE. For
SERIALIZABLE level, the search sets
shared next-key locks on the index records it encounters.
SELECT ... FROM ... LOCK IN SHARE MODE
sets shared next-key locks on all index records the search
encounters.
SELECT ... FROM ... FOR UPDATE sets
exclusive next-key locks on all index records the search
encounters and also on the corresponding clustered index
records if a secondary index is used in the search.
UPDATE ... WHERE ... sets an exclusive
next-key lock on every record the search encounters.
DELETE FROM ... WHERE ... sets an
exclusive next-key lock on every record the search
encounters.
INSERT INTO ... VALUES (...) sets an
exclusive lock on the inserted row. This lock is not a
next-key lock and does not prevent other users from
inserting into the gap before the inserted row. If a
duplicate-key error occurs, a shared lock on the duplicate
index record is set.
REPLACE is done like an
INSERT if there is no
collision on a unique key. Otherwise, an exclusive next-key
lock is placed on the row that must be updated.
While initializing a previously specified
AUTO_INCREMENT column on a table,
InnoDB sets an exclusive lock on the end
of the index associated with the
AUTO_INCREMENT column. In accessing the
auto-increment counter, InnoDB uses a
specific AUTO-INC table lock mode where
the lock lasts only to the end of the current SQL statement,
not to the end of the entire transaction. Note that other
clients cannot insert into the table while the
AUTO-INC table lock is held; see
Section 13.5.9.2, “InnoDB and AUTOCOMMIT”.
InnoDB fetches the value of a previously
initialized AUTO_INCREMENT column without
setting any locks.
INSERT INTO T SELECT ... FROM S WHERE ...
sets an exclusive non-next-key lock on each row inserted
into T. InnoDB sets
shared next-key locks on S, unless
innodb_locks_unsafe_for_binlog is
enabled, in which case it does the search on
S as a consistent read.
InnoDB has to set locks in the former
case: In roll-forward recovery from a backup, every SQL
statement must be executed in exactly the same way it was
done originally.
CREATE TABLE ... SELECT ... performs the
SELECT as a consistent read
or with shared locks, as in the previous item.
If a FOREIGN KEY constraint is defined on
a table, any insert, update, or delete that requires the
constraint condition to be checked sets shared record-level
locks on the records that it looks at to check the
constraint. InnoDB also sets these locks
in the case where the constraint fails.
LOCK TABLES sets table locks,
but it is the higher MySQL layer above the
InnoDB layer that sets these locks.
InnoDB is aware of table locks if
innodb_table_locks=1 (the default) and
AUTOCOMMIT=0, and the MySQL layer above
InnoDB knows about row-level locks.
Otherwise, InnoDB's automatic deadlock
detection cannot detect deadlocks where such table locks are
involved. Also, because in this case the higher MySQL layer
does not know about row-level locks, it is possible to get a
table lock on a table where another user currently has
row-level locks. However, this does not endanger transaction
integrity, as discussed in
Section 13.5.9.10, “Deadlock Detection and Rollback”. See also
Section 13.5.15, “Restrictions on InnoDB Tables”.
In MySQL 5.1, if the READ
COMMITTED isolation level is used or the
innodb_locks_unsafe_for_binlog system
variable is enabled, there is no InnoDB
gap locking except for foreign-key constraint checking and
duplicate-key checking. Also, record locks for non-matching
rows are released after MySQL has evaluated the
WHERE condition.


User Comments
Add your own comment.