9

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.

http8086
  • 1,306
  • 16
  • 37

2 Answers2

18

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.

Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • Hello Bill, By saying "SELECT ... FOR UPDATE are not blocked by an IX lock", then how to explain SELECT ... FOR UPDATE was blocked by another SELECT ... FOR UPDATE which indeed is IX lock – http8086 Oct 13 '14 at 01:03
  • Impressive, it was waiting for X lock, but who set that X on it? SELECT ... FOR UPDATE only asked IX lock right? – http8086 Oct 14 '14 at 09:03
  • No -- `SELECT...FOR UPDATE` locks rows that are read by the index scan, the same as if you had done an `UPDATE` or `DELETE` statement on those rows. See https://dev.mysql.com/doc/refman/5.6/en/innodb-locking-reads.html Therefore `SELECT...FOR UPDATE` tries to create X locks, and is blocked if other X locks already exist on those rows. If it acquires the locks, it blocks other `SELECT...FOR UPDATE` statements that read the same rows. – Bill Karwin Oct 14 '14 at 14:05
  • Thanks, again. This is the point and is the reason why I am confused, since according to mysql refmanual SELECT ... FOR UPDATE issued IX rather than X, "For example, SELECT ... LOCK IN SHARE MODE sets an IS lock and SELECT ... FOR UPDATE sets an IX lock." ref: https://dev.mysql.com/doc/refman/5.7/en/innodb-lock-modes.html, besides I doubt it was X lock, since X lock conflicts with shared lock, so you can not issue select(without FOR UPDATE) while there is X lock, the fact is you can select(without FOR UPDATE) even there is already SELECT ... FOR UPDATE – http8086 Oct 15 '14 at 02:56
  • Awesome, IX lock is table level lock, I thought it was row level, you deserve not only 50 points and I wish I can offer more, thank you – http8086 Oct 18 '14 at 13:20
  • Yeah, sorry if that was not clear. In Percona Server, the InnoDB status outputs the types of locks held by each transaction, and clearly labels IS and IX locks as table locks. – Bill Karwin Oct 18 '14 at 16:16
  • @BillKarwin : Can you please answer this question? It would be a great help. http://stackoverflow.com/questions/31880185/how-locks-s-x-is-ix-work-in-mysql-with-queries-like-for-update-lock-in-share-m – Shobhit_Geek Aug 12 '15 at 13:19
  • @Shobhit_Geek, sorry, I don't answer questions on StackOverflow anymore. – Bill Karwin Aug 13 '15 at 04:17
  • In the conflict matrix, what does it mean that IX and S lock are conflict? In InnoDB, I think IX is a table level lock and S lock is a row level lock, how can they be conflict with each other? – YON Nov 07 '16 at 02:01
  • @Yon, good question, I'm not sure I understand that completely myself. – Bill Karwin Nov 07 '16 at 04:55
  • @BillKarwin Sorry but I confused that. Do you mean `select for update` will set `IX` lock first, then set `X` lock? If that is the case, then second `select for update` is blocked when acquire `IX` lock because first `select for update` has get x lock and `IX` lock conflict with `X` lock, so it should be second select for update waiting when it acquire `IX` lock, right? – frank May 18 '18 at 08:40
  • @frank read https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html to see a matrix of lock compatibility. Two threads can both get IX locks, and they don't wait on each other for that lock. This allows concurrent threads to do updates on the same table, as long as their row locks don't conflict. But if a thread has a table-level X lock, it blocks other table-level IX locks. That doc page isn't very clear, but I think it makes sense if you think of table-level S/X locks like those acquired explicitly by `LOCK TABLES`, or implicitly by `ALTER TABLE`. – Bill Karwin May 18 '18 at 12:35
  • @BillKarwin Thanks for your reply and sorry to trouble you again. My questions are : 1. `select for update` will set `IX` on table first, then set `X` on match index record, right? 2. `X` and `S` lock can be table-level or row-level, right? 3. In lock type compatibility matrix of https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html, the `X` and `S` means table-level, not row-level, right? 4. 2nd `select for update` block, because 1st `select for update` have set `IX` on table and `X` on matched row, so 2nd `select for update` set `IX` on table, it is ok, but it set `X` blocked, right? – frank May 20 '18 at 02:52
  • @frank This is what I mean by the doc page isn't clear. I believe (but I can't confirm) that the doc used S and X locks to mean table-level in some parts of that doc page, and row-level in other parts of the page. But they don't make it clear which is which. But I think this is the only way to explain the inconsistency. They say IS/IX locks do not block row-level locks, but then the matrix on that page shows S/X locks conflicting with IS/IX locks, so I think they must mean table-level S/X locks at that point. – Bill Karwin May 20 '18 at 04:16
  • @BillKarwin yes, it confused me. Thank you very much. – frank May 21 '18 at 14:24
  • Nice one! But just one doubt which I would like to clear here... So when we say that there is a IS or IX lock then we mean to say that - NOT ALL CHILD NODES ARE APPLIED WITH `S` OR `X` LOCK MODE. Only the ones which are being used will be applied? – Veer Shrivastav Jun 14 '21 at 19:23
  • @VeerShrivastav, I don't know what you mean by child nodes. Do you mean rows? IS and IX locks do not apply to rows. – Bill Karwin Jun 14 '21 at 19:33
0

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

Community
  • 1
  • 1
Well
  • 73
  • 1
  • 5