Sur*_*yan 5 mysql database relational-database repeatable-read
在《高性能 Java 持久性》一书的 6.3.3.3 部分中写道,在 MySQL 可重复读取隔离级别中可能会出现丢失更新现象。这是截图:
假设以下情况(隔离级别为 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;
Run Code Online (Sandbox Code Playgroud)
问题:
tx1 提交后,MVCC 是否会检测到行版本(DB_TRX_ID)不再等于 7(而是 10)并执行回滚?或者提交会成功导致更新丢失?
Vla*_*cea 11
我是问题中提到的那本书的作者。
根据 SQL 标准,可重复读取应该防止:
该标准没有提及丢失更新,因为该标准是在2PL(两相锁定)成为事实上的并发控制机制时设计的。
如果您使用 2PL,那么可重复读取隔离级别确实可以防止丢失更新。
然而,MVCC可以通过元组的多个版本提供可重复读取,但为了防止丢失更新,它们还需要事务调度程序来跟踪某个事务读取的记录的元组修改。显然,InnoDB 不是这样工作的。
MySQL MVCC 不应该使用数据库级悲观锁定来防止丢失更新,从而导致事务回滚
MVCC 在可重复读取中不使用任何悲观锁定。唯一采用的锁定是在聚集索引上采用的间隙锁定和下一个键锁定,但这些并不能防止丢失更新。
MySQL 仅对可序列化使用悲观锁定,即使使用基于 MVCC 的 InnoDB 存储引擎,它也提供 2PL 并发控制模型。
归档时间: |
|
查看次数: |
5571 次 |
最近记录: |