【MYSQL篇】Update语句原理详解

文章目录

  • 前言
  • 缓冲池Buffer Pool
  • InnoDB 内存结构
    • redo log
    • undo log
    • Binlog
  • 总结


前言

前面的文章我们已经对MySQL的查询语句的执行流程进行了说明,感兴趣的可以去看看:

【MySQL篇】Select语句原理详解

本篇文章我们来聊聊 MySQL更新语句的执行原理。更新流程和查询流程有什么不同呢?

基本流程也是一致的,也就是说,它也要经过解析器、优化器的处理,最后交给执行器。

区别就在于拿到符合条件的数据之后的操作。

缓冲池Buffer Pool

首先,InnnoDB 的数据都是放在磁盘上的,存储引擎要操作数据,必须先把磁盘里面的数据加载到内存里面。

这里就有个问题,是不是我们需要的数据多大,我们就一次从磁盘加载多少数据到内存呢?

磁盘 I/O 的读写相对于内存的操作来说是很慢的。如果我们需要的数据分散在磁盘的不同的地方,那就意味着会产生很多次的 I/O 操作。

所以,无论是操作系统的文件管理系统也好,还是存储引擎也好,都有一个预读取的概念。也就是说,当磁盘上的一块数据被读取的时候,很有可能它附近的位置也会马上被读取到,这个就叫做局部性原理。那么这样,我们干脆每次多读取一点,而不是用多少读多少。

我们设定了一个存储引擎从磁盘读取数据到内存的最小的单位,叫做页。操作系统也有页的概念。操作系统的页大小一般是 4K,而在 InnoDB 里面,这个最小的单位默认是 16KB 大小,它是一个逻辑单位。

我们要操作的数据就在这样的页里面,数据所在的页叫数据页。我们对于数据页的操作,不是每次都直接操作磁盘,因为磁盘的速度太慢了。

使用了一种缓冲池的技术,也就是把磁盘读到的页放到一块内存区域里面。下一次读取 相同的页,先判断是不是在这个内存区域里面,如果是,就直接读取,不用再次访问磁盘。这个内存区域就叫 Buffer Pool。

接下来让我们先来看下缓冲池在整个 mysql 架构里处于什么样的地方,有一个宏观的认识。

修改数据的时候,先修改缓冲池(Buffer Pool)里面的页。内存的数据页和磁盘数据不一致的时候,我们把它叫做脏页。InnoDB 里面有专门的后台线程把 Buffer Pool 的数据写入到磁盘,每隔一段时间就一次性地把多个修改写入磁盘,这个动作就叫做刷脏。

InnoDB 内存结构

上图中可以看到很多的文件(redo log、binlog、undo log),下面我们就来分析一下它们。

redo log

思考一个问题:如果 Buffer Pool 里面的脏页还没有刷入磁盘时,数据库宕机或者重启,这些数据将会丢失。

为了避免这个问题,InnoDB 把所有对页面的修改操作专门写入一个日志文件,并且在数据库启动时从这个文件进行恢复操作(实现 crash-safe)——用它来实现事务的持久性。

image-20211013184428262

这个文件就是磁盘的 redo log(叫做重做日志),对应于/var/lib/mysql/目录下的 ib_logfile0ib_logfile1,每个 48M。

这 种 日 志 和 磁 盘 配 合 的 整 个 过 程 , 其 实 就 是 MySQL 里 的 WAL 技 术(Write-Ahead Logging),它的关键点就是先写日志,再写磁盘。

问题:同样是写磁盘,为什么不直接写到 db file 里面去?为什么先写日志再写磁盘?

我们先来了解一下随机 I/O 和顺序 I/O 的概念。

如果我们所需要的数据是随机分散在磁盘上不同页的不同扇区中,那么找到相应的数据需要等到磁臂旋转到指定的页,然后盘片寻找到对应的扇区,才能找到我们所需要 的一块数据,一次进行此过程直到找完所有数据,这个就是随机 IO,读取数据速度较慢。

假设我们已经找到了第一块数据,并且其他所需的数据就在这一块数据后边,那么就不需要重新寻址,可以依次拿到我们所需的数据,这个就叫顺序 IO。

刷盘是随机 I/O,而记录日志是顺序 I/O(连续写的),顺序 I/O 效率更高。因此先把修改写入日志文件,在保证了内存数据的安全性的情况下,可以延迟刷盘时机,进而提升系统吞吐。

这个 redo log 有什么特点?

  1. redo log 是 InnoDB 存储引擎实现的,并不是所有存储引擎都有。支持崩溃恢复是 InnoDB 的一个特性。

  2. 不是记录数据页更新之后的状态,而是记录这个页做了什么改动,属于物理日志。

  3. redo log 的大小是固定的,前面的内容会被覆盖,一旦写满,就会触发 redo log 到磁盘的同步,以便腾出空间记录后面的修改。

除了 redo log 之外,还有一个跟修改有关的日志,叫做 undo log。redo log 和 undo log 与事务密切相关,统称为事务日志。

undo log

undo log(撤销日志或回滚日志)记录了事务发生之前的数据状态(不包括 select)。如果修改数据时出现异常,可以用 undo log 来实现回滚操作(保持原子性)。

在执行 undo 的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,属于逻辑格式的日志。

undo Log 的数据默认在系统表空间 ibdata1 文件中,因为共享表空间不会自动收缩,也可以单独创建一个 undo 表空间。

有了这些日志之后,我们来总结一下一个mysql更新语句执行的流程,这是一个简化的过程。name 原值为 mayun

update user set name = 'jiangwang' where id=1;
  1. 事务开始,从内存或磁盘取到这条数据,返回给 Server 的执行器;

  2. 执行器修改这一行数据的值为 jiangwang;

  3. 记录 name=mayun 到 undo log;

  4. 记录 name=jiangwang 到 redo log;

  5. 调用存储引擎接口,在内存(Buffer Pool)中修改 name=jiangwang;

  6. 事务提交。

内存和磁盘之间,工作着很多后台线程,什么是后台线程呢?

后台线程的主要作用是负责刷新内存池中的数据和把修改的数据页刷新到磁盘。后台线程分为:master threadIO threadpurge threadpage cleaner thread

Binlog

除了 InnoDB 架构中的日志文件,MySQL 的 Server 层也有一个日志文件,叫做 binlog,它可以被所有的存储引擎使用。

binlog 以事件的形式记录了所有的 DDL 和 DML 语句(因为它记录的是操作而不是数据值,属于逻辑日志),可以用来做主从复制和数据恢复

跟 redo log 不一样,它的文件内容是可以追加的,没有固定大小限制。

在开启了 binlog 功能的情况下,我们可以把 binlog 导出成 SQL 语句,把所有的操作重放一遍,来实现数据的恢复。

binlog 的另一个功能就是用来实现主从复制,它的原理就是从服务器读取主服务器的 binlog,然后执行一遍。

有了这两个日志之后,我们来看一下一条更新语句是怎么执行的(redo 不能一次写入了):

image-20211013192144811

例如一条语句:update user set name='小马' where id=1;

  1. 先查询到这条数据,如果有缓存,也会用到缓存。

  2. 把 name 改成小马,然后调用引擎的 API 接口,写入这一行数据到内存,同时记录 redo log。这时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,可以随时提交。

  3. 执行器收到通知后记录 binlog,然后调用存储引擎接口,设置 redo log为 commit 状态。

  4. 更新完成。

总结

MySQL的更新语句的执行流程的原理,上面也已经说得很清楚了,最后我们总结一下重点:

  1. 先记录到内存(buffer pool),再写日志文件。

  2. 记录 redo log 分为两个阶段(prepare 和 commit)。

  3. 存储引擎和 server 分别记录不同的日志。

  4. 先记录 redo,再记录 binlog。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/8623.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JavaSE】方法

目录 【1】一个小例子 【2】方法概念及使用 【2.1】什么是方法(method) 【2.2】方法定义 【2.3】方法调用的执行过程 【2.4】实参和形参的关系(重要) 【1.5】没有返回值的方法 【2】函数重载 【2.1】为什么需要方法重载 【2.2】方法重载概念 【2.3】方法签名 【3】…

卷积神经网络--猫狗系列之下载、导入数据集

(由于是学习,所以文章会有一些报错及解决办法) 在Kaggle()获取数据集:(没有账号先去注册一个账号,在注册时可能会出现的问题见Kaggle注册出现一排“Captcha must be filled out.”!) https://www.kaggle.…

vue3+wangEditor5/vue-quill自定义上传音频+视频

一.各种编辑器分析 Quill 这是另一个常用的富文本编辑器,它提供了许多可定制的功能和事件,并且也有一2个官方的 Vue 3 组件 wangEditor5 wangEditor5用在Vue3中自定义扩展音频、视频、图片菜单;并扩展音频元素节点,保证音频节…

曝光调整和曝光融合论文粗读

曝光调整论文调研 M. Afifi, K. G. Derpanis, B. Ommer and M. S. Brown, “Learning Multi-Scale Photo Exposure Correction,” 2021 IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), Nashville, TN, USA, 2021, pp. 9153-9163, doi: 10.1109/CVPR4…

linux epoll/select使用区分和实例对比

Linux内核poll,ppoll,epoll,select代码位置: poll,ppoll,select相关内核实现在在fs/select.c中; epoll_ctl和epoll_wait相关函数在fs/eventpoll.c中 epoll实测不支持监听普通文件,select可以…

基于Python+MySQL所写的医院管理系统

点击以下链接获取源码资源: https://download.csdn.net/download/qq_64505944/87985429?spm1001.2014.3001.5503 目录 摘要 I 1 需求分析 1 1.1 任务描述 1 1.2 需求分析的过程 1 1.3 业务需求 2 1.4 功能描述 2 2 总体设计 3 2.1 系统开发环境 3 2.2 系统功能流…

26488-24-4,Cyclo(D-Phe-L-Pro),具有良好的生物相容性

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 【产品描述】 Cyclo(D-Phe-L-Pro)环(D-苯丙氨酸-L-脯氨酸),环二肽是由两个氨基酸通过肽键环合形成,是自然界中小的环状肽。由于其存在两个酰胺键即四个可以形成氢键的位点,环二肽可以在氢…

系统没有“internet信息服务(IIS)管理器”

系统没有“internet信息服务(IIS)管理器” 解决方案1.打开控制面板,找到并打开程序。2.找到并打开程序里的启用或关闭windows功能。3.在‘Internet Information Services’下的‘web管理工具’中找到IIS相关功能,在前面的复选框中…

Java Spring多线程

Java Spring多线程 开启一个线程1 继承java.lang.Thread类2 实现java.lang.Runnable接口3 实现Callable接口4 实现线程池ThreadPoolExecutor 操作线程线程的状态1 等待线程 join()2 中断线程 interrupt()3 守护线程(Daemon Thread) Java线程池Executors …

pinia状态管理

1.pinia是什么? 官网解释: Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。 2.为什么要使用pinia? 优点: Vue2和Vue3都支持,这让我们同时使用Vue2和Vue3的小伙伴都能很快上手。pinia中只有state、…

MySQL:七种 SQL JOINS 的实现(图文详解)

MySQL:7种SQL JOINS的实现 前言一、图示表示二、代码举例1、INNER JOIN(内连接)2、LEFT JOIN(左连接)3、RIGHT JOIN(右连接)4、OUTER JOIN(全连接)5、LEFT EXCLUDING JOI…

Android Studio 下载安装教程

在我们下载前,先来了解一下Android的4大组件: 1.活动 2.服务:类似线程,听歌时跳转发信息,后台进行播放音乐,前台交互,后台运行任务 3.广播接收者:【例1】感知充电线充电进度&#xf…