[Turn] the most comprehensive analysis of the history of the select lock (Mysql)

introduction

We have not met the interviewer asks you distinguish the following six Sql during the interview it

select * from table where id = ? select * from table where id < ? select * from table where id = ? lock in share mode select * from table where id < ? lock in share mode select * from table where id = ? for update select * from table where id < ? for update

If you can clearly say that this sql in six different transaction isolation level, whether locked, plus a shared lock or exclusive lock, the lock if there is a gap, meaning that the article did not look up.
The reason to write this article because so far the online articles in this area too one-sided, only half said, and most of them did not specify the isolation level, and wherewhether the conditions for the index followed by the column. Here, I will not list those articles in error, and we can own Baidu, most of them are not clear about.
OK, I want to answer this question, ask yourself three questions

  • What is the current transaction isolation level
  • id columns exist index
  • If there is a clustered index or the index of non-clustered index it?

OK, start answering

text

This article assumes the reader, read my "principle MySQL (Innodb) index" . If you have not seen, the amount, you remember three words right

  • innodb clustered index must exist, as a default to the primary key of a clustered index
  • There are several indexes, there are trees at the B + tree (without considering the circumstances hash index)
  • Leaf node clustered index for the real data on the disk. Leaf node or an index of a non-clustered index, pointing to cluster B + tree index.

Long-winded point below the basics

Lock Type

Shared lock (S lock): Suppose transaction T1 plus A shared lock on the data, then the transaction T2 can read the data A, you can not modify the data A.
Exclusive lock (X lock): Suppose transaction T1 plus A shared lock on the data, then the transaction T2 can not read the data A, you can not modify the data A.
We update, deleteand other statements together with the row-level locks are locks. Only LOCK TABLE … READand LOCK TABLE … WRITEyou can apply for table-level locking.
Intention shared lock (IS lock): Before a transaction acquiring (any line / or full table) S lock, we will first add IS lock on the table is located.
Intent exclusive locks (IX lock): Before a transaction acquiring (any line / or full table) X lock, will be the first increase IX lock on the table is located.

The existence of intent locks purpose?

OK, here to talk about the purpose of the existence of intent locks. Suppose transaction Tl, X lock to lock with a few records on the table, then the time table IX lock exists, i.e., intent exclusive lock. Then the time T2 to conduct transaction LOCK TABLE … WRITEtable level lock request, according to the intention can be directly determined whether the presence of the lock has a lock conflict.

Locking algorithm

My view is from the official document:
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html
add your own insights derived artificial.
ok, remember the following three, this is enough to use
Record Locks: simply translated into row lock it. Attention, the lock is locked index records! Lock is on indexed and not on the line. Attention, innodb there must be a clustered index, so row lock will eventually fall to the clustered index!
Gap Locks: Simple translation gap lock, the lock is a gap index, which is only one purpose, to prevent other things insert data. In Read Committedthe isolation level, the gap does not use the lock. Here I should add to the official website, isolation level than Read Committedat low, do not use lock gap, such as isolation level for the Read Uncommitedtime, there was no gap locks. When the isolation level Repeatable Readand Serializablewhen there is a gap will lock.
Next-Key Locks: This is understood as a Record Lock+ in front of index Gap Lock. Remember, is locked in front of the index gap! Index contains such a value, 10,11,13 and 20. Then, the lock range of the gap as follows

(negative infinity, 10]
(10, 11]
(11, 13] (13, 20] (20, positive infinity)

A snapshot of the current reading and reading

Finally the basics, and we insist on reading, which is the basis of the analysis behind!
In mysql select a snapshot into the current read and read, execute the following statement

select * from table where id = ?;

Perform a snapshot reading, reading is a snapshot version of the database record is not locked. (This statement is in isolation level Serializableis not set up, I will add later.)
Then, execution

select * from table where id = ? lock in share mode;

S plus read record will lock (shared lock), performed

select * from table where id = ? for update

Plus X will read the record lock (exclusive lock), then

Plus a table lock or row lock it?

On this point, let's recall the four transaction isolation level, as follows from weak to strong they are shown:

  • Read Uncommited(RU): Read uncommitted, a transaction can read data from another uncommitted transaction!
  • Read Committed (RC): Read Committed, a transaction can read data another transaction has been submitted!
  • Repeatable Read (RR): Repeatable read, lock join gap, to avoid the generation of the phantom read to some extent! Attention, only to a certain extent, not completely avoid! I'll explain in the next article! Also keep in mind that from the level of the gap began to join lock (this sentence down, it is useful to back)!
  • Serializable: Serialization, serialized read and write at that level, and all selectthe statements are automatically added lock in share mode, that the use of a shared lock. Therefore, in this isolation level, it is using the current reading, rather than a snapshot reading.

What about a table lock or row locks, you can see an explanation of the most popular online is that,

InnoDB row lock is achieved by the index to the index items on the lock, which is different from MySQL and Oracle, which is locked by a corresponding data line in the data block to achieve. InnoDB row lock to achieve this characteristic means: only through index conditions to retrieve the data, only InnoDB row-level locking, otherwise, would use InnoDB table lock!

We can search about these words, all you copy me, I copy you. Well, this sentence itself has two mistakes!
Error a : not achieved by operation of the lock table to lock the table, but to use Next-Key Locks!, Can be understood as a line with a gap + lock operation of the lock is achieved lock the table
for convenience of explanation, an example I, assuming as table data, pId primary key index

pId(int) name(varchar) num (int)
1 aaa 100
2 bbb 200
7 ccc 200

Execute the statement (name column without indexing)

select * from table where name = `aaa` for update

At this time, then the present lock line (the line locked) on these three records pId = 1,2,7. Further, there is a gap lock (the gap locked) on (-∞, 1) (1,2) (2,7) (7, + ∞). Thus, giving a whole table lock illusion!

ps:The conclusion of doubt, can perform their own show engine innodb status;statement analysis.

Error two : All articles do not mention isolation level!
Note that I said above, was able to lock the table, is achieved by the row lock lock + gap. Well, RUand RCdo not lock there is a gap, in this view RUand RCalso set up in it?
Therefore, this argument only RRand Serializableis valid. If the isolation level RUand RC, regardless of whether there are conditions listed on the index, will not lock table, just lock the line!

analysis

Let's begin to answer the question, assuming there are table below, pId primary key index

pId(int) name(varchar) num (int)
1 aaa 100
2 bbb 200
3 bbb 300
7 ccc 200

RC / RU + condition of non-indexed columns

(1) select * from table where num = 200
without any lock, it is a snapshot reading.
(2) select * from table where num > 200
without any lock, it is a snapshot reading.
(3) select * from table where num = 200 lock in share mode
When num = 200, there are two records. These two records corresponding pId = 2,7, S thus applied row-level locks on a clustered index pId = 2,7, using the current read.
(4) select * from table where num > 200 lock in share mode
When num> 200, there is a record. This record corresponding pId = 3, so the clustered index on pId = 3 with a line S-level lock, using the current read.
(5) select * from table where num = 200 for update
When num = 200, there are two records. These two records corresponding pId = 2,7, so add row-level locks X clustered index on pId = 2,7, using the current read.
(6) select * from table where num > 200 for update
When num> 200, there is a record. This record corresponding pId = 3, so pId = 3 clustered index on the X-level locks with a line using the current read.

RC / RU + conditions are clustered index

Well, everyone should know pId is a primary key column, so pId use is a clustered index. In fact this situation and RC / RU + condition of non-indexed columns situation is similar.
(1) select * from table where pId = 2
without any lock, it is a snapshot reading.
(2) select * from table where pId > 2
without any lock, it is a snapshot reading.
(3) select * from table where pId = 2 lock in share mode
in a clustered index on pId = 2, plus S lock for the read current.
(4) select * from table where pId > 2 lock in share mode
in a clustered index on pId = 3,7, plus S locks, read current.
(5) select * from table where pId = 2 for update
in a clustered index on pId = 2, plus X lock, to read the current.
(6) select * from table where pId > 2 for update
in a clustered index on pId = 3,7, plus X lock, to read the current.

Here, you may have questions

Why not add conditions are indexed, locked situation is the same?

ok, in fact, it is not the same. In the RC / RU isolation level, MySQL Server is optimized. If the condition is not the column index, although the full table is scanned by a clustered index, full table lock. However, MySQL Server will filter layer and do not meet the conditions of release immediately lock out, so you end result looks the same. But RC / RU + condition of non-indexed columns than in this case more than a lock release process does not meet the conditions of!

RC / RU + conditions are non-clustered index

We build on a non-unique index on the num column. At this time, there is a clustered index (primary key index, pId) formed B + tree index, which leaf nodes of the real data on the hard disk. B + tree index and the other a non-clustered index (non-unique index, num) is formed, which leaf nodes still inode, the stored value of the num column field, and the corresponding cluster index.
This can take a look at my "principle MySQL (Innodb) index" .
The next analysis begins
(1) select * from table where num = 200
without any lock, is a snapshot reading.
(2) select * from table where num > 200
without any lock, it is a snapshot reading.
(3) select * from table where num = 200 lock in share mode
When num = 200, due to the index num column, so the first stage plus line num = S locks on the index records 200 of the two. Next, a clustered index to query the tree, these two records corresponding pId = 2,7, S thus applied row-level locks on a clustered index pId = 2,7, using the current read.
(4) select * from table where num > 200 lock in share mode
When num> 200, because the index num column, so the first qualifying num = S plus lock on a row-level index 300 is recorded. Next, a clustered index to query the tree, this record corresponding pId = 3, so pId = S plus line-level lock on a clustered index 3, the use of current reading.
(5) select * from table where num = 200 for update
When num = 200, due to the index num column, so the first line in the level X num = plus two locks on the index records 200. Next, a clustered index to query the tree, these two records corresponding pId = 2,7, so add row-level locks X clustered index on pId = 2,7, using the current read.
(6) select * from table where num > 200 for update
When num> 200, because the index num column, so the first qualifying num = X plus lock on a row-level index 300 is recorded. Next, a clustered index to query the tree, this record corresponding pId = 3, so the addition pId = X on a row-level clustered index 3, the use of current reading.

RR / Serializable + conditions are non-indexed

RR level requires more consideration is the gap lock, wherein the lock of his, no matter how you check all locks the whole table. Follows
next analysis begins
(1) select * from table where num = 200
at RR level, without any lock, the snapshot is read.
In Serializable level, pId = 1,2,3,7 S plus lock on (full list of all records) clustered indexes. And
all gaps clustered index (-∞, 1) (1,2) (2,3) (3,7) (7, + ∞) was added Lock GAP
(2) select * from table where num > 200
at RR level, without any lock , it is a snapshot reading.
In Serializable level, pId = 1,2,3,7 S plus lock on (full list of all records) clustered indexes. And
all gaps clustered index (-∞, 1) (1,2) (2,3) (3,7) (7, + ∞) was added Lock GAP
(. 3) select * from table where num = 200 lock in share mode
in pId = 1,2,3, S 7 plus lock on (full list of all records) clustered indexes. And
all gaps clustered index (-∞, 1) (1,2) (2,3) (3,7) (7, + ∞) was added Lock GAP
(. 4) select * from table where num > 200 lock in share mode
in pId = 1,2,3, S 7 plus lock on (full list of all records) clustered indexes. And
all gaps clustered index (-∞, 1) (1,2) (2,3) (3,7) (7, + ∞) was added Lock GAP
(. 5) select * from table where num = 200 for update
in pId = 1,2,3, X 7 plus lock on (full list of all records) clustered indexes. And
all gaps clustered index (-∞, 1) (1,2) (2,3) (3,7) (7, + ∞) was added Lock GAP
(. 6) select * from table where num > 200 for update
in pId = 1,2,3, X 7 plus lock on (full list of all records) clustered indexes. And
All gaps clustered index (-∞, 1) (1,2) (2,3) (3,7) (7, + ∞) plus gap lock

RR / Serializable + conditions are clustered index

Well, everyone should know pId is a primary key column, so pId use is a clustered index. It characterized in that the lock case, if the wherecondition after precise query ( =the case), then there is only record lock. If wherethe conditions for range queries ( >or <case), then there is a record lock + gap lock.
(1) select * from table where pId = 2
Under RR level, without any lock, it is a snapshot reading.
In Serializable level, the current is read, added S-lock clustered index on pId = 2, gap lock does not exist.
(2) select * from table where pId > 2
In the RR level, without any lock, it is a snapshot reading.
In Serializable level, the current reading, in addition pId = S lock on the clustered index of 3,7. In (2,3) (3,7) (7 , + ∞) Lock plus GAP
(. 3) select * from table where pId = 2 lock in share mode
is the current reading, plus S lock clustered index on pId = 2, there is no gap lock.
(4) select * from table where pId > 2 lock in share mode
is the current reading, plus S lock clustered index on pId = 3,7. In (2,3) (3,7) (7 , + ∞) Lock plus GAP
(. 5) select * from table where pId = 2 for update
is the current reading, plus X lock on the clustered index pId = 2.
(6) select * from table where pId > 2 for update
In addition pId = X on a clustered index of 3,7. In (2,3) (3,7) (7 , + ∞) plus gap lock
(. 7) select * from table where pId = 6 [lock in share mode|for update]
attention, pId = 6 column does not exist, this will be added in the gap lock (3,7) on .
(8) select * from table where pId > 18 [lock in share mode|for update]
attention, pId> 18, the query result is empty. In this case, is applied in the gap lock (7, + ∞) on.

RR / Serializable + conditions are non-clustered index

Here non-clustered index, you need to distinguish whether a unique index. Because if a non-unique index, a gap locking locks is different.
Let me talk about the situation unique index. If a unique index, and where RR / Serializable + clustered index conditions are similar, the only difference is that: there are two index tree at this time, the lock is applied to the corresponding non-clustered index tree and tree clustered index ! We can self-scrutiny!
Talk about the following, non-clustered index is non-unique index, the only difference between him and the index is accurate after the inquiry by the index, not only record lock, there is gap lock. And after a precise inquiry by a unique index, there is only record lock, gap lock does not exist. In the old rules num establish non-unique index column
(1) select * from table where num = 200
in the RR level, without any lock, it is a snapshot reading.
In Serializable level, the current is read, added to an S lock clustered index on the pId = 2,7, S plus lock on the non-clustered index num = 200 in (100,200) (200,300) plus gap lock.
(2) select * from table where num > 200
In the RR level, without any lock, it is a snapshot reading.
In Serializable level, the current reading, in addition pId = S lock on the clustered index 3, S plus lock on non-clustered index is num = 300. At (200,300) (300, + ∞ ) Lock plus GAP
(. 3) select * from table where num = 200 lock in share mode
is the current reading, plus S lock clustered index on the pId = 2,7, S plus lock on non-clustered index num = 200 in (100,200) (200,300) plus gap lock.
(4) select * from table where num > 200 lock in share mode
is the current reading, in addition pId = S 3 clustered index on the lock in the lock num = S plus non-clustered index 300. At (200,300) (300, + ∞ ) plus gap lock.
(5)select * from table where num = 200 for update
It is the current reading, plus S locks on a clustered index pId = 2,7 and X plus lock on non-clustered index num = 200 in (100,200) (200,300) plus gap lock.
(6) select * from table where num > 200 for update
is the current reading, in addition pId = S clustered index on the lock 3, in addition num = X on a non-clustered index 300. At (200,300) (300, + ∞ ) plus gap lock
(. 7) select * from table where num = 250 [lock in share mode|for update]
attention, num = 250 column does not exist, this will be added in the gap lock (200,300) on.
(8) select * from table where num > 400 [lock in share mode|for update]
attention, pId> 400, the query result is empty. In this case, the gap lock is applied (400, + ∞) on.

Guess you like

Origin www.cnblogs.com/imike/p/11320138.html