I ran your samples, and you are right, this one doesnāt block.
Here is why I am convinced that a select (some sort of select anyway) does take a shared lock:
Every month or so Iām spending time solving deadlocks in poor code in mysql5.7 because a client stack (jpa) is always reading an entity (row) before the code can hope to update it (managed entity). Thread 1 takes a S lock, followed by an attempt to escalate it to X lock upon update. The thing is, another thread 2 was attempting an update before thread 1, and thread 2 is waiting for the X lock but canāt get it. Now Thread 1 wants the lock too but it is after thread 2, yet holding the S lock. Deadlock. Yes, SHOW ENGINE INNODB STATUS shows the last detected deadlock well with the situation (pasted below) among to update on a āthingā row.
(FYI, the default isolation is repeatable-read, in all this.)
So, I have a hard time believing that millions of developers and users of hibernate didnāt figure out how to avoid locking for nothing. Something is missing. All I know is that the code asked to āfindā the āthingā (by PK mind you) and then updates it. (My usual fix is to āselect ā¦for updateā since itās obviously the intent).
For such deadlock to occur, the S lock wasnāt taken ājust beforeā the X lock. A window of time had to expose the txn to collisions. So thatās a hint that the jpa āfindā issued a statement (we know itās a select) on the āthingā table.
At this point, since there is NOTHING in the select SQL to explain this shared lock, Iām hoping for a magical mysql āmodeā that nobody (in mysql nor jpa community) talks much about. (FYI, itās on AWS RDS, but I get those on a local mysql 5.7 too).
*** (1) TRANSACTION:
TRANSACTION 175274419, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 8 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 2
MySQL thread id 627088, OS thread handle 22952098592512, query id 365172765 192.168.1.100 mydatabase updating
update thing set needs_checkup=0 where id=1129
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 361 page no 25 n bits 144 index PRIMARY of table `mydatabase`.`thing` trx id 175274419 lock_mode X locks rec but not gap waiting
*** (2) TRANSACTION:
TRANSACTION 175274420, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
8 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 2
MySQL thread id 627077, OS thread handle 22952240928512, query id 365172766 192.168.1.100 mydatabase updating
update thing set needs_checkup=0 where id=1129
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 361 page no 25 n bits 144 index PRIMARY of table `mydatabase`.`thing` trx id 175274420 lock mode S locks rec but not gap
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 361 page no 25 n bits 144 index PRIMARY of table `mydatabase`.`thing` trx id 175274420 lock_mode X locks rec but not gap waiting
*** WE ROLL BACK TRANSACTION (2)
I think this hijacks the thread as much as I couldā¦ LOL
Wasnāt my intention. But it lends itself to a deeper analysis of the lock, and hopefully a bit about replication in all that.