MySQL Repeatable Read隔离级别和Lost Update现象
MySQL Repeatable Read isolation level and Lost Update phenomena
在 High Performance Java Persistence 书的 6.3.3.3 部分中写道,丢失更新现象在 MySQL 可重复读取隔离级别中是可能的。这是截图:
假设如下(隔离级别是可重复读):
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;
问题:
提交 tx1 后,MVCC 会检测到行版本(DB_TRX_ID)不再等于 7(而是 10)并执行回滚吗?或者提交将成功导致丢失更新?
根据SQL标准,可重复读应该防止:
- 脏读
- 不可重复读取
该标准未提及丢失的更新,因为该标准是在 2PL (Two-Phase Locking) 成为事实上的并发控制机制时设计的。
如果您使用 2PL,那么可重复读取隔离级别确实会阻止 Lost Update。
但是,MVCC可以通过元组的多个版本提供可重复读取,但是,为了防止丢失更新,他们还需要事务调度器来跟踪某个事务读取的记录的元组修改。显然,InnoDB 不是那样工作的。
shouldn't MySQL MVCC prevent Lost Update using database-level Pessimistic Locking resulting in transaction rollback
MVCC 不在可重复读取中使用任何悲观锁定。唯一使用的锁是聚集索引上的间隙锁和下一个键锁,但这些锁不能防止丢失更新。
MySQL 仅对可序列化使用悲观锁定,它提供了 2PL 并发控制模型,即使在使用基于 MVCC 的 InnoDB 存储引擎时也是如此。
在 High Performance Java Persistence 书的 6.3.3.3 部分中写道,丢失更新现象在 MySQL 可重复读取隔离级别中是可能的。这是截图:
假设如下(隔离级别是可重复读):
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;
问题:
提交 tx1 后,MVCC 会检测到行版本(DB_TRX_ID)不再等于 7(而是 10)并执行回滚吗?或者提交将成功导致丢失更新?
根据SQL标准,可重复读应该防止:
- 脏读
- 不可重复读取
该标准未提及丢失的更新,因为该标准是在 2PL (Two-Phase Locking) 成为事实上的并发控制机制时设计的。
如果您使用 2PL,那么可重复读取隔离级别确实会阻止 Lost Update。
但是,MVCC可以通过元组的多个版本提供可重复读取,但是,为了防止丢失更新,他们还需要事务调度器来跟踪某个事务读取的记录的元组修改。显然,InnoDB 不是那样工作的。
shouldn't MySQL MVCC prevent Lost Update using database-level Pessimistic Locking resulting in transaction rollback
MVCC 不在可重复读取中使用任何悲观锁定。唯一使用的锁是聚集索引上的间隙锁和下一个键锁,但这些锁不能防止丢失更新。
MySQL 仅对可序列化使用悲观锁定,它提供了 2PL 并发控制模型,即使在使用基于 MVCC 的 InnoDB 存储引擎时也是如此。