So I have a table with id
as INT NOT NULL
as the PK
. When I do query 1 (Trans1) in a transaction I get 3 rows locked, and when I do query 2 (Trans2) also in a transaction, I do also get 3 rows locked.
Example Table:
+----+--------------------------------------+-------------------------+
| id | some_val | created_at |
+----+--------------------------------------+-------------------------+
| 1 | 33aa186d-e2de-4c41-aa50-000000000001 | 2019-03-17 15:15:21.130 |
| 2 | 33aa186d-e2de-4c41-aa50-000000000002 | 2019-03-17 15:15:31.292 |
| 3 | 33aa186d-e2de-4c41-aa50-000000000003 | 2019-03-17 15:16:01.396 |
+----+--------------------------------------+-------------------------+
Trans1:
SELECT * FROM example WHERE id >= 1 AND id <= 3 FOR UPDATE;
INNODB Status
---TRANSACTION 10750, ACTIVE 4 sec
3 lock struct(s), heap size 360, 4 row lock(s)
MySQL thread id 23, OS thread handle 0x7f41f5153700, query id 11504 172.19.0.1 root
Trans2:
SELECT * FROM example WHERE id IN (1,2,3) FOR UPDATE;
INNODB Status
---TRANSACTION 10854, ACTIVE 11 sec
2 lock struct(s), heap size 360, 3 row lock(s)
MySQL thread id 23, OS thread handle 0x7f41f5153700, query id 11652 172.19.0.1 root
Now, even though the results seem similar, they are quite different in regarding of what's actually locked. For starter, no inserts are possible while Trans1 is in progress, while inserts are possible during Trans2. Also, if table has only 3 rows, how is INNODB showing 4 locks (I guess is the next auto increment, thus no inserts possible).
I would like to understand why does this happen, as I've read about gap locking and next-key lock, but none makes sense about what's happening on Trans1.
Best Answer
If we use the performance_schema.data_locks table we get a better idea which locks are different.
Here we can see the
supremum
, or gap lock is the additional lock occurs with the RANGE query. While the is possible to avoid because because id 3 exists as a primary key, the MySQL developers haven't implemented this as it complicates locking and adds checks in a rather critical and time sensitive execution path.Note, setting
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
will make locks equivalent as gap locks are onlyREPEATABLE READ
.Schema (MySQL v8.0)
Query #1
Query #2
Query #3
Query #4
Query #5
Query #6
Query #7
Query #8
View on DB Fiddle