一条更新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. 二十二、导入DXF文件

    x

  2. 13_奈奎斯特稳定性判据_Nyquist Stability Criterion_Part 1

    A曲线内有4个极点两个零点,则B曲线绕(0,0)逆时针两圈 A曲线是nyqyict contour中的曲线,P是A曲线内的()极点个数,Z是()极点个数,N是曲线B逆时针围绕(-1,0)的圈数 没过( ...

  3. 前端性能优化(Application Cache篇)

    正巧看到在送书,于是乎找了找自己博客上记录过的一些东西来及其无耻的蹭书了~~~ 小广告:更多内容可以看我的博客 之前在segmentfault上刷问题看到一个关于manifest的问题,很好奇就研究了 ...

  4. 微信小程序开发快速入手

    1.在page中的修改数据的setData函数,需要传递的是一个对象. that.setData({ src: res.tempFilePath }) 2.在 onload 事件中,可以获取wx.na ...

  5. Linux 0.11源码阅读笔记-高速缓冲

    高速缓冲 概念 高速缓冲区是内存中的一块内存,在块设备与内核其它程序之间起着一个桥梁作用.内核程序如果需要访问块设备中的数据,都需要经过高速缓冲区来间接的操作. 高速缓冲区结构 高速缓冲区被划分为1k ...

  6. Linux 0.11源码阅读笔记-总览

    Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...

  7. 【MarkDown】使用

    1. 插入代码 在代码前后加上三个点样式的标识符: ``` 效果: 我是代码 1-1 换行 &符号加上 "ensp;"   2. 标题样式定制 # 一级标题 ## 二级标题 ...

  8. break,return,continue的区别和作用

    学习目标: 理解break.return.continue在循环中的区别和作用 学习内容: 1.break break表示结束当前所在的循环. 循环输出到3,当i等于4后,跳出当前循环,继续向下执行循 ...

  9. Factorials and Powers of Two

    分析:我们可以看出这道题目的描述并不是很复杂,就是说对于一个给定的整数n,我们能否把他拆成k个powerful的数,也就是说这k个数要么是2的幂次,要么是某个数的阶乘,并且我们要让当前的k越小越好:然 ...

  10. Thinkphp3.2.3 where注入 浅分析漏洞原理及修复

    0x01引子 0x02分析 找到截断方法 找到_parseType的入口 找到生成sql语句的代码 0x03 poc链 0x04 利用示范 payload: http://localhost:3000 ...