MySQL 更新一条记录与原记录一样会怎么样?
MySQL InnoDB引擎下,更新一条记录与原记录一样会怎么样?
我们创建了一个简单的表 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);
AI写代码
这时候,表 t 里有唯一的一行数据 (1,2)。假设,我现在要执行:
mysql> update t set a=2 where id=1;
AI写代码
即要更新的记录 实际上与原记录一样
你会看到这样的结果:

结果显示,匹配 (rows matched) 了一行,修改 (Changed) 了 0 行。
仅从现象上看,MySQL 内部在处理这个命令的时候,可以有以下三种选择:
所有更新操作都会先读取数据进行处理。MySQL会获取这些数据并检查a字段的值是否已发生变化。如果a字段的值与预期一致,则无需修改即返回结果并结束整个操作。
MySQL 采用了 InnoDB 支持的「修改为 (1,2)」接口。然而,在检测到数据值与原有状态一致时,引擎未对数据进行更新处理,并立即返回给客户端请求处理。
InnoDB 严格按照"将该值修改为 (1,2)"这一操作进行了处理,并对需要加锁的部分进行了加锁操作;同时对需要更新的部分进行了相应的更新操作。
答案是 选项3
验证:
在选项中提到 MySQL 从数据库读取数据后发现返回的数据与原有记录一致,并因此不进行更新直接返回结果。为了验证这一现象,在数据库中创建一个测试场景:例如,在表 t 中插入记录 (1,2) 的情况下进行测试。

在 session B 中的 update 操作已被阻止。然而要实现加锁这一操作,则必须依赖于 InnoDB 的能力。因此可以排除选项 1。
MySQL调用了InnoDB引擎提供的接口是否存在未更新的情况呢?为了验证这一点我采用了可见性测试假设当前表中的数据为(1 2)

在 session A 中的第二个 select 语句采用了一种基于一致性的读取方式(即快照模式),因此无法观察到其他 session(如 session B)的操作更新。当前返回的结果是 (1,3),这表明该查询看到了一个新版本;而这一新版本只能源自于 session A 执行自身 update 操作时所生成。
MySQL无需先检查值是否相同?假如你进行检查的话,则无需过多地使用InnoDB进行操作。
MySQL 已经得到了广泛认可。在这一特定语句中 MySQL 认为我们所看到的数据仅为一个唯一标识符(ID=1)。而想要设置的数据是(a=3)仅仅根据这些信息无法判断是否无需修改。为了验证这一点 请参考下面的例子

参考:《MySQL实战45讲----15讲课后习题》
