问题
Using the MySQL isolation level of Repeatable Read.
Given table test
having non-indexed column quantity
:
id | quantity
--------------------
1 | 10
2 | 20
3 | 30
Tx1 executes 1st, note it is not committed yet, meaning that all the acquired locks are not released yet.
Tx1:
START TRANSACTION;
DELETE FROM test WHERE quantity=10;
Now executing Tx2
Tx2:
START TRANSACTION;
INSERT INTO test(quantity) VALUES (40);
COMMIT;
For Tx2 I get the following result:
Lock wait timeout exceeded; try restarting transaction
I understand that, as the quantity
column is not indexed, the delete
statement does a full table scan, locks all the rows( doesn't matter the where
condition matches or not) and also applies gap locks before every and after the last index record in a Clustered Index resulting in a fully blocked table hence the insert
statement from tx2 cannot acquire a lock for a row to be inserted.
From MySQL manual(for Repeatable Read isolation level):
For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it.
For other search conditions, InnoDB locks the index range scanned, using gap locks or next-key locks to block insertions by other sessions into the gaps covered by the range (this is used in my case).
Taking into account that the locking in any given isolation level is applied for preventing the phenomenas
I'm a little bit confused what is the reason to block the whole table in this case, I mean what kind of phenomena
is prevented with blocking the whole table in this case ?
回答1:
By default, InnoDB uses consistent snapshots in Repeatable Read isolation level, meaning that you get repeatable reads for both tuples and ranges.
Even if the SQL standard says that Phantom Reads are prevented by Serializable, and that Repeatable Read might not prevent it, it is not a problem if a lower isolation level provides better guarantees than what the standard has it mind.
For more details about how gap locking works, check out this article.
来源:https://stackoverflow.com/questions/53452571/what-phenomena-does-mysql-try-to-prevent-by-locking-the-whole-table-upon-executi