innodb - 当主键更改时,mvcc 如何工作?
问题描述
在 MVCC 文档中,它说当“选择查询”找到记录时,它会将 transactionId 与自己的 id 进行比较,以判断是否可以看到数据以及是否应该从重做日志中重建历史记录。我的问题是如果找不到原始记录怎么办,如何保持一致的阅读?
考虑以下示例:
create table tb_a (id bigtint not null primary key auto_increment, name varchar(100) not null default "");
// isolation level is RR
// transaction 1
select * from tb_a where id = 1; // it returns (1, "a")
// transaction 2
// another trx update the first line with its primary key
update tb_a set id = 3 where id = 1;
commit;
// transaction 1
select * from tb_a where id = 1; // still gets (1, "a")
过滤器 id = 1 的主键找不到该行,因为历史记录在重做日志中,并且 innodb 中的更新发生在原地。那么innodb是如何对待这种事情的,并且仍然保持一致性呢?
解决方案
更改 PK 列可能是旧记录的“删除”和新行的“插入”。我认为这意味着有些东西留在了表中,但被标记为已删除(直到两个事务提交后的清理)。
类似的UNIQUE
关键变化。其他事务需要能够看到已删除的行以检查 dup 键。
每行的每个版本(旧/新)都有一个事务 ID。所以...
可重复阅读:
当一个事务开始时,它被分配一个“事务ID”。这是一个单调递增的序列号,用于标识可能被修改的行。对于事务隔离 = RR,查询只能“看到”具有该 trx id(或更早)的行。这解释了为什么你的决赛SELECT
看到它做了什么。而且,请注意,该查询实际上(据我所知)是重新执行的。
您的其他 txn 具有更高的 trx id。它创建了该行的“更新”副本。因此,该行至少有两个副本漂浮在周围。隔离模式加上 trx id 控制每个事务可以“看到”哪一行。
推荐阅读
- regex - 替换四位数熊猫
- reactjs - reactjs中如何在Router Link(菜单导航)中传递多个状态
- python - 在 python 中运行 fortran 子例程时出现奇怪的错误
- php - 由于未正确配置 htaccess 文件,POST 无法正常工作
- java - 使用 Javamail 无法接收来自 POP3 GMAIL 的邮件,出现 SSLHandshakeException
- python - 无法使用循环预测 Keras 中的单个实例
- php - 将 jquery 对象附加到 formData()
- python - tkinter 输入字段的遍历顺序有问题
- bash - 从 awk 生成的制表符分隔文件填充关联数组的疑难解答
- email - 如何在邮箱参数中使用变量?