Why is an IX-lock compatible with another IX-lock in InnoDB?

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?

Final explanation:

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.


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
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.

Leave a Reply

Your email address will not be published. Required fields are marked *