0
点赞
收藏
分享

微信扫一扫

update修改了 0 行情况

搬砖的小木匠 2023-09-06 阅读 76
  • 问题
我们创建了一个简单的表 t,并插入一行,然后对这一行做修改。

mysql> CREATE TABLE `t` (
`id` int(11) NOT NULL primary key auto_increment,
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB;
insert into t values(1,2);
这时候,表 t 里有唯一的一行数据 (1,2)。假设,我现在要执行:
mysql> update t set a=2 where id=1;
结果显示,匹配 (rows matched) 了一行,修改 (Changed) 了 0 行。
仅从现象上看,MySQL 内部在处理这个命令的时候,可以有以下三种选择:

1.更新都是先读后写的,MySQL 读出数据,发现 a 的值本来就是 2,不更新,直接返回,执行结束;
2.MySQL 调用了 InnoDB 引擎提供的“修改为(1,2)”这个接口,但是引擎发现值与原来相同,不更新,直接返回;
3.InnoDB 认真执行了“把这个值修改成 (1,2)这个操作,该加锁的加锁,该更新的更新。

你觉得实际情况会是以上哪种呢?你可否用构造实验的方式,来证明你的结论?
进一步地,可以思考一下,MySQL 为什么要选择这种策略呢?
  • 分析
第一个选项,我们可以用一个锁实验来确认。
假设,当前表 t 里的值是 (1,2)。
session Bupdate 语句被 blocked 了,加锁这个动作是 InnoDB 才能做的,所以排除选项 1

第二个选项,我们可以用一个可见性实验来确认。
假设当前表里的值是 (1,2)。
session A 的第二个 select 语句是一致性读(快照读),它是不能看见 session B 的更新的。

现在它返回的是 (1,3),表示它看见了某个新的版本,这个版本只能是 session A 自己的 update 语句做更新的时候生成。

  • 参考答案
选项 3,即:InnoDB 认真执行了“把这个值修改成 (1,2)这个操作,该加锁的加锁,该更新的更新
举报

相关推荐

0 条评论