官网地址
https://dev.mysql.com/doc/refman/5.5/en/innodb-transaction-isolation-levels.html
这里主要是说事务隔离级别,以及对锁的影响
Transaction isolation is one of the foundations of database processing. Isolation is the I in the acronym ACID; the isolation level is the setting that fine-tunes the balance between performance and reliability, consistency, and reproducibility of results when multiple transactions are making changes and performing queries at the same time.
InnoDB
offers all four transaction isolation levels described by the SQL:1992 standard: READ UNCOMMITTED
, READ COMMITTED
, REPEATABLE READ
, and SERIALIZABLE
. The default isolation level for InnoDB
is REPEATABLE READ
.
A user can change the isolation level for a single session or for all subsequent connections with the SET TRANSACTION
statement. To set the server's default isolation level for all connections, use the --transaction-isolation
option on the command line or in an option file. For detailed information about isolation levels and level-setting syntax, see Section 13.3.6, “SET TRANSACTION Syntax”.
InnoDB
supports each of the transaction isolation levels described here using different locking strategies. You can enforce a high degree of consistency with the default REPEATABLE READ
level, for operations on crucial data where ACID compliance is important. Or you can relax the consistency rules with READ COMMITTED
or even READ UNCOMMITTED
, in situations such as bulk reporting where precise consistency and repeatable results are less important than minimizing the amount of overhead for locking. SERIALIZABLE
enforces even stricter rules than REPEATABLE READ
, and is used mainly in specialized situations, such as with XA transactions and for troubleshooting issues with concurrency and deadlocks.
The following list describes how MySQL supports the different transaction levels. The list goes from the most commonly used level to the least used.
-
This is the default isolation level for
InnoDB
. Consistent reads within the same transaction read the snapshot established by the first read. This means that if you issue several plain (nonlocking)SELECT
statements within the same transaction, theseSELECT
statements are consistent also with respect to each other. See Section 14.8.2.3, “Consistent Nonlocking Reads”.For locking reads (
SELECT
withFOR UPDATE
orLOCK IN SHARE MODE
),UPDATE
, andDELETE
statements, locking depends on whether the statement uses a unique index with a unique search condition, or a range-type search condition.-
For a unique index with a unique search condition,
InnoDB
locks only the index record found, not the gap before it. -
For other search conditions,
InnoDB
locks the index range scanned, using gap locks or next-key locks to block insertions by other sessions into the gaps covered by the range. For information about gap locks and next-key locks, see Section 14.8.1, “InnoDB Locking”.
-
-
Each consistent read, even within the same transaction, sets and reads its own fresh snapshot. For information about consistent reads, see Section 14.8.2.3, “Consistent Nonlocking Reads”.
For locking reads (
SELECT
withFOR UPDATE
orLOCK IN SHARE MODE
),UPDATE
statements, andDELETE
statements,InnoDB
locks only index records, not the gaps before them, and thus permits the free insertion of new records next to locked records. Gap locking is only used for foreign-key constraint checking and duplicate-key checking.Because gap locking is disabled, phantom problems may occur, as other sessions can insert new rows into the gaps. For information about phantoms, see Section 14.8.4, “Phantom Rows”.
If you use
READ COMMITTED
, you must use row-based binary logging.Using
READ COMMITTED
has additional effects:-
For
UPDATE
orDELETE
statements,InnoDB
holds locks only for rows that it updates or deletes. Record locks for nonmatching rows are released after MySQL has evaluated theWHERE
condition. This greatly reduces the probability of deadlocks, but they can still happen. -
For
UPDATE
statements, if a row is already locked,InnoDB
performs a “semi-consistent” read, returning the latest committed version to MySQL so that MySQL can determine whether the row matches theWHERE
condition of theUPDATE
. If the row matches (must be updated), MySQL reads the row again and this timeInnoDB
either locks it or waits for a lock on it.
Consider the following example, beginning with this table:
CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB; INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2); COMMIT;
-
In this case, table has no indexes, so searches and index scans use the hidden clustered index for record locking (see Section 14.11.2.1, “Clustered and Secondary Indexes”).
Suppose that one client performs an UPDATE
using these statements:
SET autocommit = 0;
UPDATE t SET b = 5 WHERE b = 3;
Suppose also that a second client performs an UPDATE
by executing these statements following those of the first client:
SET autocommit = 0;
UPDATE t SET b = 4 WHERE b = 2;
As InnoDB
executes each UPDATE
, it first acquires an exclusive lock for each row, and then determines whether to modify it. If InnoDB
does not modify the row, it releases the lock. Otherwise, InnoDB
retains the lock until the end of the transaction. This affects transaction processing as follows.
When using the default REPEATABLE READ
isolation level, the first UPDATE
acquires x-locks and does not release any of them:
x-lock(1,2); retain x-lock
x-lock(2,3); update(2,3) to (2,5); retain x-lock
x-lock(3,2); retain x-lock
x-lock(4,3); update(4,3) to (4,5); retain x-lock
x-lock(5,2); retain x-lock
The second UPDATE
blocks as soon as it tries to acquire any locks (because first update has retained locks on all rows), and does not proceed until the first UPDATE
commits or rolls back:
--comment: REPEATABLE-READ级别的情况下,由于所有记录没有索引,扫描所有记录的时候不管是否匹配条件,这些记录都被锁上
x-lock(1,2); block and wait for first UPDATE to commit or roll back
If READ COMMITTED
is used instead, the first UPDATE
acquires x-locks and releases those for rows that it does not modify:
--comment: 而在READ-COMMITTED级别的情况,同样会扫描所有记录并对所有记录上锁,但会对比匹配的记录解锁
x-lock(1,2); unlock(1,2)
x-lock(2,3); update(2,3) to (2,5); retain x-lock
x-lock(3,2); unlock(3,2)
x-lock(4,3); update(4,3) to (4,5); retain x-lock
x-lock(5,2); unlock(5,2)
For the second UPDATE
, InnoDB
does a “semi-consistent” read, returning the latest committed version of each row to MySQL so that MySQL can determine whether the row matches the WHERE
condition of the UPDATE
:
x-lock(1,2); update(1,2) to (1,4); retain x-lock
x-lock(2,3); unlock(2,3)
x-lock(3,2); update(3,2) to (3,4); retain x-lock
x-lock(4,3); unlock(4,3)
x-lock(5,2); update(5,2) to (5,4); retain x-lock
-
The effects of using the
READ COMMITTED
isolation level are the same as enabling theinnodb_locks_unsafe_for_binlog
configuration option, with these exceptions:-
Enabling
innodb_locks_unsafe_for_binlog
is a global setting and affects all sessions, whereas the isolation level can be set globally for all sessions, or individually per session. -
innodb_locks_unsafe_for_binlog
can be set only at server startup, whereas the isolation level can be set at startup or changed at runtime.
READ COMMITTED
therefore offers finer and more flexible control thaninnodb_locks_unsafe_for_binlog
. -
-
SELECT
statements are performed in a nonlocking fashion, but a possible earlier version of a row might be used. Thus, using this isolation level, such reads are not consistent. This is also called a “dirty read.” Otherwise, this isolation level works likeREAD COMMITTED
. -
This level is like
REPEATABLE READ
, butInnoDB
implicitly converts all plainSELECT
statements toSELECT ... LOCK IN SHARE MODE
ifautocommit
is disabled. Ifautocommit
is enabled, theSELECT
is its own transaction. It therefore is known to be read only and can be serialized if performed as a consistent (nonlocking) read and need not block for other transactions. (To force a plainSELECT
to block if other transactions have modified the selected rows, disableautocommit
.)