gpt4 book ai didi

mysql - MVCC 如何与 MySql 中的 Lock 一起工作?

转载 作者:行者123 更新时间:2023-12-02 02:05:57 25 4
gpt4 key购买 nike

我知道在Mysql中使用锁或者MVCC可以实现并发控制,比如repeatable-reading。 但不知道MVCC是如何避免幻读的。在其他地方了解到一般是通过MVCC和Gap-Lock来实现的,但是我目前的理解是MVCC不需要锁,即更新和删除都是使用undo-logs来实现的。 如果是,MVCC 和锁机制如何协同工作?

例如,为了避免幻读,MVCC 会在 T1 中的某些行上添加间隙锁吗? 如果是这样,MVCC如何在T2发生更新时,一般只是追加一个update undo-log?还是阻止它?

最佳答案

MySQL(特别是 InnoDB)不支持 REPEATABLE-READ 锁定语句。例如,UPDATEDELETESELECT...FOR UPDATE。这些语句总是锁定最近提交的行版本,就好像事务隔离级别是 READ-COMMITTED。

您可以观察到这种情况:

mysql> create table mytable (id int primary key, x int);
Query OK, 0 rows affected (0.05 sec)

mysql> insert into mytable values (1, 42);
Query OK, 1 row affected (0.02 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from mytable;
+----+------+
| id | x |
+----+------+
| 1 | 42 |
+----+------+

到目前为止,还不错。现在打开第二个窗口并更新值:

mysql> update mytable set x = 84;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0

现在回到第一个窗口,由于 REPEATABLE-READ,非锁定读取仍然查看原始值,但锁定读取查看最近提交的版本:

mysql> select * from mytable;
+----+------+
| id | x |
+----+------+
| 1 | 42 |
+----+------+
1 row in set (0.00 sec)

mysql> select * from mytable for update;
+----+------+
| id | x |
+----+------+
| 1 | 84 |
+----+------+
1 row in set (0.00 sec)

mysql> select * from mytable;
+----+------+
| id | x |
+----+------+
| 1 | 42 |
+----+------+
1 row in set (0.00 sec)

您可以根据需要来回多次,并且同一事务可以返回两个值,具体取决于进行锁定读取还是非锁定读取。

这是 InnoDB 的一个奇怪行为,但它允许读取不被阻塞。我使用了其他 MVCC 实现,例如 InterBase/Firebird,它们以不同的方式解决了这个问题。它会阻塞读取,直到第二个窗口中的事务提交或回滚。如果它回滚,那么锁定读取可以读取原始值。如果其他事务提交,则锁定读取会出错。

InnoDB 在如何实现 MVCC 上做出了不同的选择,以避免阻塞读取。但它会导致奇怪的行为,即锁定读取必须查看最新提交的行版本。

正如歌曲所说,“你不能总是得到你想要的。”

关于mysql - MVCC 如何与 MySql 中的 Lock 一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68443220/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com