0

这是我的情况:

CREATE TABLE test (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, value INT DEFAULT 0);
INSERT INTO test (id, value) VALUES (1, 10);

会议 A

START TRANSACTION;
SELECT value FROM test WHERE id = 1;
  10

会议 B

START TRANSACTION;
SELECT value FROM test WHERE id = 1;
  10

会议 A

UPDATE test SET value = value + 2 WHERE id = 1;
SELECT value FROM test WHERE id = 1;
  12
COMMIT;

会议 B

SELECT value FROM test WHERE id = 1;
  10

在这里我得到了预期的结果,因为Session B有一个独立的 row 副本id = 1,即来自Session A的提交在这里可见。

但是当我更新这一行时,隔离中断:

会议 B

UPDATE test SET value = value + 3 WHERE id = 1;

根据这个关于 MVCC 的视频https://www.youtube.com/watch?v=sxabCqWsFHg(15'00 ),这个更新应该被拒绝。但是 MySQL 接受了这个更新。

会议 B

SELECT value FROM test WHERE id = 1;
  15

所以这个选择得到了一个意想不到的结果:来自Session A的提交在Session B中是可见的。

我的 MySQL 版本是 5.7.26,隔离级别是 REPEATABLE-READ。

=== 更新 ===

对于带有 RocksDB 引擎的 MariaDB 10.4.10,此案例按预期工作。

会话 B

UPDATE test SET value = value + 3 WHERE id = 1;

它返回

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction (snapshot conflict)
4

1 回答 1

1

在 InnoDB 中,锁定语句不遵守 REPEATABLE-READ 隔离。

锁总是影响最近提交的行版本。所以它们的行为就像你使用了 READ-COMMITTED 一样。

这会影响UPDATEandDELETE以及锁定读取,例如SELECT...FOR UPDATE.

但是一旦你更新一行,新版本就会在你的事务中可见。

于 2019-12-22T07:35:08.543 回答