Advertisement

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写代码

即要更新的记录 实际上与原记录一样

你会看到这样的结果:

image

结果显示,匹配 (rows matched) 了一行,修改 (Changed) 了 0 行。

仅从现象上看,MySQL 内部在处理这个命令的时候,可以有以下三种选择:

所有更新操作都会先读取数据进行处理。MySQL会获取这些数据并检查a字段的值是否已发生变化。如果a字段的值与预期一致,则无需修改即返回结果并结束整个操作。

MySQL 采用了 InnoDB 支持的「修改为 (1,2)」接口。然而,在检测到数据值与原有状态一致时,引擎未对数据进行更新处理,并立即返回给客户端请求处理。

InnoDB 严格按照"将该值修改为 (1,2)"这一操作进行了处理,并对需要加锁的部分进行了加锁操作;同时对需要更新的部分进行了相应的更新操作。

答案是 选项3

验证:

在选项中提到 MySQL 从数据库读取数据后发现返回的数据与原有记录一致,并因此不进行更新直接返回结果。为了验证这一现象,在数据库中创建一个测试场景:例如,在表 t 中插入记录 (1,2) 的情况下进行测试。

image

在 session B 中的 update 操作已被阻止。然而要实现加锁这一操作,则必须依赖于 InnoDB 的能力。因此可以排除选项 1。


MySQL调用了InnoDB引擎提供的接口是否存在未更新的情况呢?为了验证这一点我采用了可见性测试假设当前表中的数据为(1 2)

image

在 session A 中的第二个 select 语句采用了一种基于一致性的读取方式(即快照模式),因此无法观察到其他 session(如 session B)的操作更新。当前返回的结果是 (1,3),这表明该查询看到了一个新版本;而这一新版本只能源自于 session A 执行自身 update 操作时所生成。


MySQL无需先检查值是否相同?假如你进行检查的话,则无需过多地使用InnoDB进行操作。

MySQL 已经得到了广泛认可。在这一特定语句中 MySQL 认为我们所看到的数据仅为一个唯一标识符(ID=1)。而想要设置的数据是(a=3)仅仅根据这些信息无法判断是否无需修改。为了验证这一点 请参考下面的例子

image

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

全部评论 (0)

还没有任何评论哟~