• MySQL更新一条已经存在的sql语句是怎么执行的


    MySQL更新一条已经存在的sql语句是怎么执行的

    1. 问题描述

    今天看到一个有意思的问题,就是Mysql更新一条已经存在的语句是怎么执行的,结果显示,匹配(rows matched)了一行,修改(Changed)了0行。,实际上执行完成sql会提示Affected rows: 0,是的,你没看错更新0行,那这就有意思了,mysql到底是更新了没有呢,具体是在哪一层更新的呢?根据之前写的文章《MySQL是如何执行一条SQL更新语句》知道更新sql语句是在server层先读取原来值,然后调用数据库引擎,最后由数据库引擎执行完成返回给server层,根据以上分析有三种情况。

    仅从现象上看,MySQL内部在处理这个命令的时候,可以有以下三种选择:
    1.更新都是先读后写的,MySQL读出数据,发现a的值本来就是2,不更新,直接返回,执行结束。
    2.MySQL调用了InnoDB引擎提供的“修改为(1,2)”这个接口,但是引擎发现值与原来相同,不更新,直接返回;
    3.InnoDB认真执行了"把这个值修改成(1,2)"这个操作,该加锁的加锁,该更新的更新。

    2. 分析验证

    1.首先关闭Navicat自动提交事务
    关闭Navicat自动提交:菜单栏-》工具-》选项-》选中,自动开始事务

    2.创建表

    -- -测试update
    create table demo(
    id int(11) not null primary key auto_increment,
    a int(11) default null
    )engine=InnoDB;
    
    -- 插入1,2
    insert into demo values(1,2);
    -- 查看插入是否成功
    select * from demo;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.每种情况分析
    第一个选项是,MySQL读出数据,发现值与原来相同,不更新,直接返回,执行结束。这里我们可以用一个锁实验来确认。
    在这里插入图片描述
    Navicat开启两个窗口,sessionA不提交,sessionB阻塞住,等sessionA commit后,sessionB执行成功。session B的update 语句被blocked了,加锁这个动作是InnoDB才能做的,所以排除选项1。

    第二个选项是,MySQL调用了InnoDB引擎提供的接口,但是引擎发现值与原来相同,不更新,直接返回。有没有这种可能呢?这里我用一个可见性实验来确认。
    在这里插入图片描述session A的第二个select 语句是一致性读(快照读),它是不能看见session B的更新的。
    现在它返回的是(1,3),表示它看见了某个新的版本,这个版本只能是session A自己的update语句做更新的时候生成。

    所以,答案应该是选项3,即:InnoDB认真执行了“把这个值修改成(1,2)"这个操作,该加锁的加锁,该更新的更新。

    然后你会说,MySQL怎么这么笨,就不会更新前判断一下值是不是相同吗?如果判断一下,不就不用浪费InnoDB操作,多去更新一次了?
    其实MySQL是确认了的。只是在这个语句里面,MySQL认为读出来的值,只有一个确定的(id=1), 而要写的是(a=3),只从这两个信息是看不出来“不需要修改”的。作为验证,可以执行下面的例子
    在这里插入图片描述执行sql(注意关闭自动提交,开启两个不同的事务,按照顺序执行)

    -- sessionA
    begin;
    -- 1,2
    select * from demo;
    
    -- sessionB
    update demo set a=3 where id =1;
    -- 1,3
    select * from demo;
    commit;
    
    -- sessionA
    update demo set a=3 where id =1 and a=3;
    -- 1,2
    select * from demo where id =1;
    commit;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    dubbo.xsd的配置
    python:绘制回归预测结果真实值和预测值之间的散点密度图
    使用Java合并PDF文档
    [Algorithm][前缀和][和为K的子数组][和可被K整除的子数组][连续数组][矩阵区域和]详细讲解
    六种最常见的软件供应链攻击
    Spring Cloud Gateway负载均衡
    手把手教你编写LoadRunner脚本
    面试官:工作中用过锁么?说说乐观锁和悲观锁的优劣势和使用场景
    基于javaweb的在线考试系统(java+springboot+vue+jsp+mysql)
    Windows 10 - Mysql - zip压缩包详细安装教程
  • 原文地址:https://blog.csdn.net/m0_37583655/article/details/128174413