MySQL Repeatable Read isolation level and Lost Upd

2020-08-01 08:41发布

问题:

In High Performance Java Persistence book's 6.3.3.3 section it's written that Lost Update phenomena is possible in MySQL Repeatable Read isolation level. This is the screenshot:

Assuming the following(isolation level is REPEATABLE READ):

              tx1                     |                tx2
-----------------------------------------------------------------------------------
START TRANSACTION;                    |
SELECT * FROM test WHERE id = 1;      |
( say, DB_TRX_ID = 7 at this moment)   |
                                      |
                                      |  START TRANSACTION;
                                      |  SELECT * FROM test WHERE id = 1;
                                      |  UPDATE test SET name="x" WHERE id = 1;
                                      |  COMMIT;(say, makes DB_TRX_ID = 10)
                                      |
UPDATE test SET name="y" WHERE id = 1;|
COMMIT;

Question:

Upon tx1 commit will MVCC detect that the row version(DB_TRX_ID) is not equal to 7 anymore(instead it's 10) and perform a rollback ? Or the commit will be succeeded causing a Lost Update ?

回答1:

In Repeatable Read isolation level shouldn't MySQL MVCC prevent Lost Update using database level Pessimistic Locking resulting into transaction rollback?

According to the SQL standard, Repeatable Read should prevent:

  • dirty reads
  • non-repeatable reads

The standard says nothing about lost updates because the standard was designed when 2PL (Two-Phase Locking) was the facto Concurrency Control mechanism.

If you use 2PL, then the Repeatable Read isolation level will, indeed, prevent a Lost Update.

However, MVCC can provide Repeatable Reads via multiple versions of a tuple, but, in order to prevent Lost Updates, they also need the transaction scheduler to track tuple modifications for the records read by a certain transaction. Apparently, InnoDB does not work like that.

shouldn't MySQL MVCC prevent Lost Update using database-level Pessimistic Locking resulting into transaction rollback

Now, if you read carefully the Transactions chapter in my High-Performance Java Persistence book, you will find out that MVCC does not use any Pessimistic Locking in Repeatable Read. The only locks taken are the gap and next-key locks taken on the clustered index, but those don't prevent Lost Updates.

MySQL uses Pessimistic Locking for Serializable only, which provides a 2PL Concurrency Control model, even when using the MVCC_based InnoDB storage engine.