一条更新SQL的内部执行

学习MySQL实战45讲,非常推荐学

还是老图:

上文复习

在执行查询语句的时候,会执行连接器(总要连上才能搞事情),然后去查询缓存(MySQL8+删除了),有数据返回,没数据进行分析器-优化器-执行器-执行引擎流程并且其特点是如果该表上有更新,都会把缓存结果清空

MySQL整体来看可以分为两块:一块是Server层,它主要做的是MySQL功能层面的事情;还有一块是引擎层,负责存储相关的具体事宜;

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

流程:

  1. 连接器:连接数据库
  2. 分析器:分析词法和语法解析知道这是更新语句
  3. 优化器:决定使用ID进行索引
  4. 执行器:具体执行,找到改行然后更新

更新对查询来说,涉及到了两个重要的日志模块,redo log(重做日志)InnoDB特有的,binlog(归档日志)Server中存在的,只要持续学习数据库方面,这两个是绕不过的。

redo log(重做日志)

在InnoDB中redo log的大小是固定的,可以配置为一组4个文件,每个文件的大小是1GB,那么这块redo log总共就可以记录4GB的操作(可以自己设置)。

MySQL中的问题:

如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程IO成本、查找成本都很高

解决问题:

WAL技术:Write-Ahead Logging

  1. 写日志
  2. 写磁盘

执行流程:

为什么redo log具有crash-safe的能力

为什么 redo log 具有 crash-safe 的能力,是 binlog 无法替代的?

redo log的被动刷盘机制

明确定义:

write:刷盘

fsync:持久化到磁盘

write(刷盘)指的是MySQL从buffer pool中将内容写到系统的page cache中,并没有持久化到系统磁盘上。这个速度其实是很快的。

fsync指的是从系统的cache中将数据持久化到系统磁盘上。这个速度可以认为比较慢,而且也是IOPS升高的真正原因。

redo log是物理日志,记录的是“在某个数据页上做了什么修改”,内部结构是基于页的,记录了这个页的字段值变化,只要crash后读取redo log进行重放就可以恢复数据。(因为redo log是循环写的,如果满了InnoDB就会执行真正写盘)。

好处是不用每一次操作都实时把数据写盘,就算crash后也可以通过redo log重放恢复,所以能够实现快速响应SQL语句。

binlog(归档日志)

MySQL刚开始是使用的自带引擎MyISAM,但其没有crash-safe,binlog日志只能用于归档,5.5版本之后引入InnoDB,通过redo log来实现crash-safe能力。

redo log与binlog的区别

  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
  2. redo log 是物理日志记录的是在某个数据页上做了什么修改;binlog 是逻辑日志记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
  3. redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志

update内部执行流程:

流程图:图中浅色框表示是在 InnoDB 内部执行的,深色框表示是在执行器中执行的

其中redo log分为两个阶段提交:这是为了让两份日志之间的逻辑一致

  1. redo log prepare阶段
  2. commit阶段

好处:保证redo log和binlog都能同时失败或者成功。

论证两阶段提交的必要性:

如果不采用两阶段提交,那么redo log和binlog是单独的逻辑,由此引出下面两种提交方式:

  1. 先写redo log,后写binlog
  2. 先写binlog,后写redo log

还是以update为例:

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

先写redo log,后写binlog

在redo log写完,binlog没写完的时候,MySQL 进程异常重启,因为其实先写入内存的,所以MySQL崩溃后仍然能把数据恢复

根据备份恢复后c的值为1.但由于binlog没有写完就崩溃了,这时候binlog就没有记录这条语句的操作,使用binlog恢复的时候就会少一次更新,c的值为0,这就与原库的值不同了。

先写binlog,后写redo log与上面逻辑相同都会造成恢复的数据与原库值不同;

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

但是当按照上述流程图来说,在进行两阶段提交的时候,即A、B时刻出现crash,是怎么处理的。

流程如下:



B时刻发生crash后对应的是2(a)的情况,崩溃恢复过程中事务会被提交。

由此引出的很多问题,感兴趣的朋友可以看下MySQL实战45讲答疑篇第一章

备份的流程:

  1. 找到最近的一次全量备份,从这个备份恢复到临时库;
  2. 从备份的时间点开始,将备份的 binlog 依次取出来,重放到中午误删表之前的那个时刻。

备份恢复的数据的场景:

  1. 误操作后需要恢复数据
  2. 要扩容的时候,也需要再多搭建一些备库来增加系统的读能力的时候,用全量备份加上应用binlog 来实现的。如果这个“不一致”就会导致你的线上出现主从数据库不一致的情况

一条更新SQL的内部执行及日志模块的更多相关文章

  1. JAVA中处理事务的程序--多条更新SQL语句的执行(包括回滚)

    在与数据库操作时,如果执行多条更新的SQL语句(如:update或insert语句),在执行第一条后如果出现异常或电脑断电, 则后面的SQL语句执行不了,这时候设定我们自己提交SQL语句,不让JDBC ...

  2. MySql 学习之 一条更新sql的执行过程

    上一篇文章咱们说了一条查询sql的执行过程.如果没有看过上一篇文章的可以去看下上一篇文章,今天咱们说说一条更新sql的执行过程. 上面一条sql是将id为1的分数加上10. 那么它的执行流程是怎样的呢 ...

  3. MySQL中一条更新语句是如何执行的

    1.创建表的语句和更新的语句 这个表的创建语句,这个表有一个主键ID和一个整型字段c: mysql> create table T(ID int primary key, c int); 如果要 ...

  4. 当程序执行一条查询语句时,MySQL内部到底发生了什么? (说一下 MySQL 执行一条查询语句的内部执行过程?

    先来个最基本的总结阐述,希望各位小伙伴认真的读一下,哈哈: 1)客户端(运行程序)先通过连接器连接到MySql服务器. 2)连接器通过数据库权限身份验证后,会先查询数据库缓存是否存在(之前执行过相同条 ...

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

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

  6. 一条查询SQl是怎样执行的

    MySQL的逻辑架构图 大体来说,MySQL可以分为Server层和存储引擎层两部分. Server层包括连接器.查询缓存.分析器,优化器等,涵盖MySQL的大多核心服务功能,以及所有的内置函数,存储 ...

  7. MySQL概述 - 一条查询sql语句的执行过程

    Server层 连接器 建立连接.获取权限.维持和管理连接. 连接建立比较复杂,建议使用长连接 定期断开长连接 mysql_reset_connection指令 查询缓存 建议关闭,任何更新操作会此t ...

  8. MySQL:一条SQL是如何执行的

    目录 MySQL基本架构 Server层 连接器 查询缓存 分析器 优化器 执行器 存储引擎层 InnoDB MyISAM Memory SQL执行流程 MySQL基本架构 在讲SQL语句是如何执行之 ...

  9. MySql 学习之 一条查询sql的执行过程

    相信大家都接触过Mysql数据库,而且也肯定都会写sql.我不知道大家有没有这样的感受,反正我是有过这样的想法.就是当我把一条sql语句写完了,并且执行完得到想要的结果.这时我就在想为什么我写这样的一 ...

随机推荐

  1. c++中的左值和右值的理解

    1.左值和右值的概念 C++中左值(lvalue)和右值(rvalue)是比较基础的概念,虽然平常几乎用不到,但C++11之后变得十分重要,它是理解 move/forward 等新语义的基础. 左值与 ...

  2. Spring Framework远程代码执行漏洞复现(CVE-2022-22965)

    1.漏洞描述 漏洞名称 Spring Framework远程代码执行漏洞 公开时间 2022-03-29 更新时间 2022-03-31 CVE编号 CVE-2022-22965 其他编号 QVD-2 ...

  3. Anaconda安装tensorflow和keras(gpu版,超详细)

    本人配置:window10+GTX 1650+tensorflow-gpu 1.14+keras-gpu 2.2.5+python 3.6,亲测可行 一.Anaconda安装 直接到清华镜像网站下载( ...

  4. vue点击按钮复制文本框内容

    1.npm进行安装 npm install clipboard --save 2.在需要使用的组件中import 引用方法:import Clipboard from 'clipboard'; 3.添 ...

  5. 基于node实现一个简单的脚手架工具(node控制台交互项目)

    实现控制台输入输出 实现文件读写操作 全原生实现一个简单的脚手架工具 实现vue-cli2源码 一.实现控制台输入输出 关于控制台的输入输出依然是基于node进程管理对象process,在proces ...

  6. Python中用类实现对象和封装

    """ 用类实现对象和封装 对象:对应客观世界的事物,将描述事物的一组数据和与这组数据有关的操作封装在一起, 形成一个实体,这个实体就是对象 类:具有相同或相似性质的对象 ...

  7. 用asmlib方式创建oracle集群ASM磁盘(oracleasm)

    创建asm磁盘的几种方式 创建asm方式很多主要有以下几种 1.Faking方式 2.裸设备方式 3.udev方式(它下面有两种方式) 3.1 uuid方式 3.2 raw方式(裸设备方式) 4.as ...

  8. oracle查看当前用户表结构、主键、索引

    1.查询表的所有列及其属性 select t.*,c.COMMENTS from user_tab_columns t,user_col_comments c where t.table_name = ...

  9. Java学习day17

    继续学习了IO流的一些常用类以及GUI基础 做了自己的第一个Frame窗口 在做第一个Frame窗口时程序报错:java: 无法从静态上下文中引用非静态 变量 this 查看后发现不小心把MyFram ...

  10. rabbitmq简单运用

    <?php /** * 生产者 */ $connection = new AMQPConnection([ 'host' => '192.168.23.130', 'port' => ...