问题
According to innodb lock mode lock type compatibility matrix
X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible
IX is compatible with IX, but the fact is if we acquire one IX lock by select c1 from z where c1 = 1 for update
in session 1, trying to acquire IX by select c1 from z where c1 = 1 for update
will be blocked in session 2, so I think they are not compatible. Did I miss anything here?
Edit after answer accepted:
The reason why SELECT ... FOR UPDATE in one session blocks SELECT ... FOR UPDATE in another is they are asking not only IX lock on table level but also X lock on row level. It is all because of X lock.
回答1:
https://dev.mysql.com/doc/refman/5.6/en/innodb-lock-modes.html says:
Thus, intention locks do not block anything except full table requests (for example, LOCK TABLES ... WRITE). The main purpose of IX and IS locks is to show that someone is locking a row, or going to lock a row in the table.
This means multiple threads can acquire IX locks. These locks are at the table-level, not the row-level. An IX lock means that the thread holding it intends to update some rows somewhere in the table. IX locks are only intended to block full-table operations.
It may shed some light if you consider that it goes both ways -- if a full-table operation is in progress, then that thread has a table-level lock that blocks an IX lock.
DML operations must first acquire an IX lock before they can attempt row-level locks. The reason is that you don't want DML to be allowed while an ALTER TABLE
is in progress, or while some other thread has done LOCK TABLES...WRITE
.
Row-level changes like UPDATE
, DELETE
, SELECT..FOR UPDATE
are not blocked by an IX lock. They are blocked by other row-level changes, or by an actual full table lock (LOCK TABLES
, or certain DDL statements). But aside from those table operations, multiple threads running DML can probably work concurrently, as long as they are each working on a set of rows that don't overlap.
Re your comment:
The second SELECT...FOR UPDATE
is not blocked waiting on the IX lock, it's blocked waiting on the X (row-level) locks on rows that are already locked by X-locks in another thread.
I just tried this and then I ran SHOW ENGINE INNODB STATUS
so I could see the blocked transaction:
---TRANSACTION 71568, ACTIVE 12 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 10, OS thread handle 140168480220928, query id 288 localhost root statistics
select * from test where id=1 for update
------- TRX HAS BEEN WAITING 12 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 802 page no 3 n bits 72 index `PRIMARY` of table `test`.`test`
trx id 71568 lock_mode X locks rec but not gap waiting
See? It says it's waiting for to be granted the lock with lock_mode X on the primary key index of the table test
. That's a row-level lock.
Re your confusion about LOCK IN SHARE MODE
:
You're talking about three levels of SELECT
.
SELECT
requests no locks. No locks block it, and it blocks no other locks.SELECT ... LOCK IN SHARE MODE
requests an IS lock on the table, and then S locks on rows that match the index scan. Multiple threads can hold IS locks or IX locks on a table. Multiple threads can hold S locks at the same time.SELECT ... FOR UPDATE
requests an IX lock on the table, and then X locks on rows that match the index scan. X locks are exclusive which means they can't any other thread to have an X lock or an S lock on the same row.
But neither X nor S locks care about IX or IS locks.
Think of this analogy: imagine a museum.
Many people, both visitors and curators, enter the museum. The visitors want to view paintings, so they wear a badge labeled "IS". The curators may replace paintings, so they wear a badge labeled "IX". There can be many people in the museum at the same time, with both types of badges. They don't block each other.
During their visit, the serious art fans will get as close to the painting as they can, and study it for lengthy periods. They're happy to let other art fans stand next to them before the same painting. They therefore are doing SELECT ... LOCK IN SHARE MODE
and they have "S" locks because they at least don't want the painting to be replaced while they're studying it.
The curators can replace a painting, but they are courteous to the serious art fans, and they'll wait until these viewers are done and move on. So they are trying to do SELECT ... FOR UPDATE
(or else simply UPDATE
or DELETE
). They will acquire "X" locks at this time, by hanging a little sign up saying "exhibit being redesigned." The serious art fans want to see the art presented in a proper manner, with nice lighting and some descriptive placque. They'll wait for the redesign to be done before they approach (they get a lock wait if they try).
Also, you've probably been in a museum where more casual visitors wander about, trying to stay out of other people's way. They look at paintings from the middle of the room, not approaching too close. They can look at the same paintings other viewers are looking at, and they can peek over the shoulders of the serious art fans, to look at those paintings being viewed too. They may even gawk at the curators while they're replacing paintings (they don't care if they glimpse a painting that hasn't been mounted and lighted properly yet). So these casual visitors don't block anyone, and no one blocks their viewing. They are just doing SELECT
and they don't request any locks.
But there are also construction workers who are supposed to tear down walls and stuff, but they won't work while there's anyone in the building. They'll wait for everyone to leave, and once they start their work, they won't let anyone in. That's how the presence of either IS and IX badges block DDL (the construction work), and vice-versa.
回答2:
IS and IX locks allow access by multiple clients. They won't necessarily conflict until they try to get real locks on the same rows.
But a table lock (ALTER TABLE, DROP TABLE, LOCK TABLES) blocks both IS and IX, and vice-versa.
Therefore the IX-lock compatible with another IX-lock (they both are table level) or IX-lock conflict with another X-lock(table level not row level)
Reference: http://www.slideshare.net/billkarwin/innodb-locking-explained-with-stick-figures
来源:https://stackoverflow.com/questions/25903764/why-is-an-ix-lock-compatible-with-another-ix-lock-in-innodb