1. MR.
Translation from the official document: Locking Reads
If you query data and then insert or update related data within the same transaction, the regular SELECT statement does not give enough protection. Other transactions can update or delete the same rows you just queried. InnoDB supports two types of locking reads that offer extra safety:
If you query the data, and then insert or modify the relevant data in the same transaction, the conventional select statement does not provide adequate protection. Other transactions can modify or delete a row you are querying. InnoDB supports two read lock can provide security mechanism:
SELECT … LOCK IN SHARE MODE sets a shared mode lock on any rows that are read. Other sessions can read the rows, but cannot modify them until your transaction commits. If any of these rows were changed by another transaction that has not yet committed, your query waits until that transaction ends and then uses the latest values.
SELECT ... LOCK IN SHARE MODE is set on the line that reads a shared lock, other session can read these lines, but you can not modify them before the transaction commits. If these lines, there are other matters to be modified has not been submitted, your query will wait until after the end of the transaction using the latest value.
For index records the search encounters, SELECT … FOR UPDATE locks the rows and any associated index entries, the same as if you issued an UPDATE statement for those rows. Other transactions are blocked from updating those rows, from doing SELECT … LOCK IN SHARE MODE, or from reading the data in certain transaction isolation levels. Consistent reads ignore any locks set on the records that exist in the read view. (Old versions of a record cannot be locked; they are reconstructed by applying undo logs on an in-memory copy of the record.)
Record index search encountered an index entry SELECT ... FOR UPDATE locks the line and any associated, identical to those lines and you execute update statement. Other transactions will be blocked in the implementation of these lines update operations, acquire a shared lock, or read some data from the transaction isolation level and so on. Consistency read ( Consistent Nonlocking Reads ) ignores any lock on the record of the reading view. (The old version of the recording can not be locked; they are rebuilt by applying undo log is on the in-memory copy of the record.)
All locks set by LOCK IN SHARE MODE and FOR UPDATE queries are released when the transaction is committed or rolled back.
Note
Locking of rows for update using SELECT FOR UPDATE only applies when autocommit is disabled (either by beginning transaction with START TRANSACTION or by setting autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked.
All shared locks and exclusive locks set of query lock will be released after the transaction is committed or rolled back.
NOTE:
using SELECT FOR UPDATE row lock for the update operation applies only to autocommit is disabled (when the start START TRANSACTION autocommit transaction or set to 0). If autocommit is enabled, compliant lines will not be locked.
Second, summary
Here Reference: shared locks in MySQL with exclusive lock
SELECT ... LOCK IN SHARE MODE: shared locks (S locks, share locks). Other transactions can read data but can not modify the data until all shared locks are released.
If the transaction after row of data plus a shared lock, can read and write; other transactions that data can be shared locks, but can not add exclusive lock, and can only read data, the data can not be modified.
SELECT ... FOR UPDATE: exclusive lock (X lock, exclusive locks). If the transaction after the data plus exclusive lock, other transactions can not add any of the data lock. Obtain an exclusive lock transaction not only read data, but also to modify the data.
Note: Ordinary default select statement is not locked, but the default CUD operations plus exclusive lock.
Third, verify
Note: Use mysql version 5.8.9, InnoDB transaction isolation level is the default isolation level repeatable read (Repeated Read).
Verify the following situations:
- After the current transaction acquires a shared lock, you can read and write, whether other transactions can read and write and acquire a shared lock;
- After the two transactions acquire shared locks, can you update operations;
- After the current transaction acquires an exclusive lock, other transactions if you can read and write and acquire a shared lock;
- Whether the data can be added to a more exclusive lock;
- Relations row locks and indexes;
- Index data repetition rate is too high will result in a full table scan;
1, after the current transaction acquires a shared lock, can read and write, whether other transactions can read and write and acquire a shared lock: you can read, you can acquire a shared lock, can not write
The current transaction can write:
1 transaction after obtaining a row of data shared locks, transaction 2 updates the row blocking:
After the transaction submitted 1, 2 transaction was successful:
2, two transactions while sharing a row of data after acquiring lock, can perform an update operation: not
Two transactions simultaneously acquire data in a row shared locks, transaction 1 updates the row blocking:
After submitting the transaction 2, 1 transaction was successful:
3, the current transaction to obtain data in a row exclusive lock, other transactions if you can read and write and acquire a shared lock on the data line: other transactions can be read, can not acquire a shared lock, can not write
可以读该行数据:
不可以获取该行数据共享锁:
不可以更新该行数据:
4、是否可对一条数据加多个排他锁:不可以
5、行锁和索引的关系:查询字段未加索引(主键索引、普通索引等)时,使用表锁
注:InnoDB行级锁基于索引实现。
未加索引时,两种行锁情况为(使用表锁):
- 事务1获取某行数据共享锁,其他事务可以获取不同行数据的共享锁,不可以获取不同行数据的排他锁
- 事务1获取某行数据排他锁,其他事务不可以获取不同行数据的共享锁、排他锁
加索引后,两种行锁为(使用行锁):
- 事务1获取某行数据共享锁,其他事务可以获取不同行数据的排他锁
- 事务1获取某行数据排他锁,其他事务可以获取不同行数据的共享锁、排他锁
未加索引表结构:
未加索引,事务1获取某行数据共享锁,事务2获取不同行数据共享锁成功:
未加索引,事务1获取某行数据共享锁,事务2更新不同行数据阻塞:
未加索引,事务1获取某行数据排他锁,事务2获取不同行数据共享锁阻塞:
未加索引,事务1获取某行数据排他锁,事务2获取不同行数据排他锁阻塞:
加索引后表结构:
加索引后,事务1获取某行数据共享锁,事务2更新不同行数据成功:
加索引后,事务1获取某行数据排他锁,事务2获取不同行数据共享锁成功:
加索引后,事务1获取某行数据排他锁,事务2获取不同行数据排他锁成功:
6、索引数据重复率太高会导致全表扫描:当表中索引字段数据重复率太高,则MySQL可能会忽略索引,进行全表扫描,此时使用表锁。可使用 force index 强制使用索引。
表结构:
CREATE TABLE `room` (
`id` int(11) NOT NULL AUTO_INCREMENT, `uid` int(11) NOT NULL, `username` varchar(200) NOT NULL DEFAULT '', `state` varchar(255) NOT NULL DEFAULT '-1', `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `index_uid` (`uid`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
表数据:
获取 uid = ‘11’ 的数据的行锁并更新,但更新失败:
降低数据重复率,更新成功:
强制使用索引,更新成功:force index(index_uid)
Note: If you use table locks here, why other transactions can acquire an exclusive lock?
A: Because the use of force index
, and InnoDB row-level locking based on the index to achieve , so here are using a row lock.
Four, InnoDB row lock type Introduction
Reference: Mysql InnoDB those in the lock mechanism
Three types of InnoDB row lock:
- Record Lock: lock on an index entry, locking qualified rows. Other transactions can not modify, and delete lock entries;
- Gap Lock: on the "gap" between the index entry lock, the lock range of records, the index does not include the items themselves. Inserting data within the range of other transactions can not be locked;
- Next-key Lock: Lock index entry itself and the index range, namely Record combination of Gap Lock and Lock. Magic solve reading problems.