首先创建一张表;

  1. create table T(ID int primary key,c int);

如果要更新ID=2这行+1;应该这样写

  1. update T set c=c+1 where ID=2;

执行这句操作首先还是要与数据库建立连接这是连接器的工作。
在一个表进行更新操作时,这张表的缓存就会失效。

接下来分析器会对这条跟新语句进行语法和词法分析,如果有问题就会报错提示。然后优化器会决定使用ID的索引情况,最后执行器负责执行,找到这行然后更新。

与查询操作不同的是,更新操作涉及到两个重要的日志模块。redo log(重做日志),bin log(归档日志)。如果接触到MySQL这两个日志是必学的。

redo log

如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后在更新,这个过程IO成本、查找成本都很高。为了解决这个问题,MySQL的设计者就用了类似于酒店掌柜的黑板记录来提升效率。
WAL技术简称Write-Ahead Logging ,他的关键就是先写日志再写磁盘。写磁盘的时间并不是固定的,他是等到系统比较空闲的时候才写入磁盘。

当一条记录需要更新的时候,InnoDB引擎就会把记录写进redo log里面,并更新内存。这个时候就算更新完成了。同时,InnoDB引擎会在适当的时候将这个操作记录更新到磁盘中。

还有需要注意的是,InnoDB的redo log 是固定大小的,比如以组分为4个文件,每个文件大小是1GB,那么这个日子就可以记录4GB的操作。从头开始写,写到结尾再从头开始写。是一个循环。

有了redo log InnoDB就可以保证即使数据库发生了异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe.

要理解crash-safe这个概念,可以想象赊账的例子,只要赊账记录在了黑板上或卸载账本上,即使店长忘记了,但也有黑板上或账本上的明确数目。

bin log

上面所说的redo log 是InnoDB引擎独有的日志,而Server层也有自己的日志,称为bin log(归档日志)。

其实bin log日志出现的时间比redo log早,因为最开始MySQL是没有InnoDB存储引擎的,5.5之前是MyISAM。但是MyISAM没有crash-safe的能力,binlog日志只能永固归档。而InnoDB是另一个公司使用的一套日志系统来实现crash-safe能力。

两种日志的区别

  1. redo log 是InnoDB独有的;bing log 是MySQL的Server层实现的,所有引擎都可以使用。
  2. redo log 是物理日志,记录的是在某个数据页改动了哪些;bin log 是逻辑日志,记录的是SQL语句具体操作。
  3. redo log 是循环写的,空间固定会用完;binlog是可以追加写入的。追加写是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

update语句内部流程

  1. 执行器先找到引擎ID=2这行,ID是主键,引擎直接用树搜索找到这一行。如果ID=2这行数据被就在内存中那就不需要再调入内存直接返回给执行器;否则需要先从磁盘读入内存,然后再返回。
  2. 执行器拿到引擎给的行数据,把行值+1,得到新的一行数据,在调用引擎接口写入这行新数据。
  3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态。然后告知执行器执行完成了,随时可以提交事务。
  4. 执行器生成这个操作的bin log,并把bin log 写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交状态,更新完成。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上图中浅绿色的是在InnoDB引擎中执行的,墨绿色是在Server层完成的。

如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。

MySQL45讲:一条update语句是怎样执行的的更多相关文章

  1. 如何将多条update语句合并为一条

    需求: 如何将多条update语句合并为一条update语句:如,update table1 set col='2012' where id='2014001'      update table1  ...

  2. Sql Server执行一条Update语句很慢,插入数据失败

    今天同事要我修改服务器数据库里面的2条数据,查看服务器上的SQL Server数据库的时候,发现这几天数据没有添加成功,然后发现磁盘很快就满了,执行Update语句时,执行半天都提示还在执行,查询语句 ...

  3. 完蛋,公司被一条 update 语句干趴了!

    大家好,我是小林. 昨晚在群划水的时候,看到有位读者说了这么一件事. 在这里插入图片描述 大概就是,在线上执行一条 update 语句修改数据库数据的时候,where 条件没有带上索引,导致业务直接崩 ...

  4. 一条update语句到底加了多少锁?带你深入理解底层原理

    迎面走来了你的面试官,身穿格子衫,挺着啤酒肚,发际线严重后移的中年男子. 手拿泡着枸杞的保温杯,胳膊夹着MacBook,MacBook上还贴着公司标语:"我爱加班". 面试开始,直 ...

  5. MySQL:一条更新语句是如何执行的

    目录 引言 更新流程图 更新流程说明 第一步:更新数据 数据页内存 Change Buffer 第二步:缓存日志内容 redo log buffer binlog cache 第三步:日志写入磁盘 两 ...

  6. 一条 SQL 语句是如何执行的

    一条 SQL 语句是如何执行的 SQL查询语句 select * from user where ID=10; MySQL 的基本架构可以分为 Server 层和存储引擎两部分.Server 层又包含 ...

  7. 一条SQL语句是如何执行的?--Mysql45讲笔记记录 打卡day1

    写在前面的话:回想以前上班的时候,空闲时间还是挺多的,但是都荒废了.如今找工作着实费劲了.但是这段时间在极客时间买了mysql45讲,就好像发现了新大陆一样,这是我认真做笔记的第一天,说实话第一讲我已 ...

  8. sql执行万条update语句优化

    几个月没有更新笔记了,最近遇到一个坑爹的问题,顺道记录一下.. 需求是这样的:一次性修改上万条数据库. 项目是用MVC+linq的. 本来想着用 直接where() 1 var latentCusto ...

  9. 用一条UPDATE语句交换两列的值

    在SQL UPDATE语句中,"="右侧的值在整个UPDATE语句中都是一致的,所有更新同时发生!因此以下语句将在没有临时变量的情况下交换两列的值: UPDATE table SE ...

随机推荐

  1. js中的bind、apply、call、callee、caller的区别

    1.bind.apply与call的区别与使用 相同点:2者是函数原型的一个方法,因此调用者都必须是函数,第1个参数都是对象.作用是,用另一个对象替换当前对象,另一对象也即是你传的第一个参数.通常用于 ...

  2. C++ 虚函数表与多态 —— 关键字 override 的用法

    override 仅能用于虚函数,他属于C++新特性,是重写覆盖的意思,他的存在仅仅是为了提高代码的可阅读性: 作用: 1. 提示程序的阅读者,这个函数是重写父类的功能. 2. 防止程序员在重写父类的 ...

  3. java web简单的对数据库存数据

    1.建立一个表,分别有Coursename,teachername,Place,Id;这些数据跟sql语句中的相对应 2.在src包目录下创建这些类 3.在WebContent目录下创建jsp,Mai ...

  4. 2020-2021-1 20209307《Linux内核原理与分析》第六周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第六周作业> 这个作业的目标 & ...

  5. 自顶向下redis4.0(5)持久化

    redis4.0的持久化 目录 redis4.0的持久化 简介 正文 rdb持久化 save命令 bgsave命令 rdb定期保存数据 进程结束保存数据 aof持久化 数据缓冲区 刷新数据到磁盘 ap ...

  6. js第二次作业——2019.10.16

    第一题:完成省城市的三级联动(包括湖南省),附代码和效果图. 1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 </head> ...

  7. NET 5 使用RabbitMQ以及Kafka区别

    区别 1.应用场景方面RabbitMQ:用于实时的,对可靠性要求较高的消息传递上.kafka:用于处于活跃的流式数据,大数据量的数据处理上.2.架构模型方面producer,broker,consum ...

  8. GDI+中发生一般性错误 Winform Image.Save(mstream, ImageFormat.Png)引发

    在处理图片时,读取本地图像文件,进行另存时发生GDI+中发生一般性错误 . 具体情况如下: 用OpenFileDialog打开图像文件,文件名为filename StreamReader sr = n ...

  9. qt界面设计

    需求 需要不同界面同样的位置有上下的公共部分 分解 在WPF中我亦接触到需要这样做的程序.在wpf中我将上下公共部分作为界面基类,其它界面都继承这个基类.我用qt准备定义一个stackedpanel, ...

  10. 《深入理解 Java 虚拟机》读书笔记

    第二章 Java 内存区域与内存溢出溢出 程序计数器 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的 ...