在高性能Java持久性书的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)并执行回滚吗?还是提交将成功导致更新丢失?
发布于 2018-11-30 20:48:47
我是问题中提到的书的作者。
根据SQL标准,可重复读取应防止:
该标准没有提到丢失的更新,因为该标准是在2PL (两相锁定)是事实上的并发控制机制时设计的。
如果使用2PL,那么可重复的读取隔离级别确实会阻止丢失更新。
但是,MVCC可以通过一个元组的多个版本提供可重复读取,但是为了防止丢失更新,它们还需要事务调度程序来跟踪某个事务读取的记录的元组修改。显然,InnoDB不是那样工作的。
MySQL MVCC不应该使用数据库级悲观锁定防止丢失更新,从而导致事务回滚吗?
在可重复读取中,MVCC不使用任何悲观锁定。唯一使用的锁是聚集索引上的间隙锁和下一个键锁,但这些锁不能防止丢失更新。
MySQL只对序列化使用悲观锁定,这提供了2PL并发控制模型,即使在使用基于MVCC的InnoDB存储引擎时也是如此。
发布于 2022-08-10 06:59:24
如果我知道的是正确的,MySQL在可重复读取隔离级别使用MVCC。
顺便说一句,MVCC本身并不能防止更新丢失。
因此,在可重复读取隔离级别。对于MySQL,我们必须使用使用独占锁的select ... for update,这样才能防止丢失的更新。
杰菲。
PostgreSQL还使用MVCC。
在postgreSQL的可重复读取隔离级别上,它使用了第一次更新赢策略,因此在以后的事务B更新X之前更新了X的早期事务A将获胜,如果A成功提交,则B必须进行回滚。如果A失败并回滚,则B可以成功提交。
MySQL和postgreSQL都在读取可重复隔离级别使用MVCC,但是它们对于如何解决丢失的更新问题有不同的策略。
https://stackoverflow.com/questions/53562850
复制相似问题