【MYSQL篇】Update语句原理详解

这篇具有很好参考价值的文章主要介绍了【MYSQL篇】Update语句原理详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

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

【MySQL篇】Select语句原理详解

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

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

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

缓冲池Buffer Pool

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

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

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

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

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

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

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

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

【MYSQL篇】Update语句原理详解

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

InnoDB 内存结构

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

redo log

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

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

【MYSQL篇】Update语句原理详解

这个文件就是磁盘的 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 不能一次写入了):

【MYSQL篇】Update语句原理详解

例如一条语句: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。文章来源地址https://www.toymoban.com/news/detail-495647.html

到了这里,关于【MYSQL篇】Update语句原理详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ //练习 2.11 指出下面的语句是声明还是定义:

    练习 2.11 指出下面的语句是声明还是定义: ( a ) extern int ix = 1024; ( b ) int iy; ( c ) extern int iz; 环境:Linux Ubuntu(云服务器) 工具:vim   解释 ( a ) 定义ix为1024。 ( b ) 声明并定义iy。 ( c ) 声明而非定义iz。

    2024年01月19日
    浏览(57)
  • 【postgresql 基础入门】UPSERT语句,INSERT违反约束条件时可以转变为UPDATE语句,UPDATE与INSERT的合体

    ​ 专栏内容 : postgresql内核源码分析 手写数据库toadb 并发编程 个人主页 :我的主页 管理社区 :开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 入门准备 postgrersql基础架构 快速使用 初始化集群 数据库服务管理 psql客户端使用 pgAdmin图形化客户端

    2024年03月12日
    浏览(51)
  • MybatisPlus 使用 saveOrUpdate 详解(慎用),及问题解决方法&mysql保存或更新 ON DUPLICATE KEY UPDATE

    今天的想法是,要在插入数据库时,如果有某某一个主要字段的值重复,则不插入,否则则插入! 看了一下mybatis-Plus是有这个saveOrUpdate 方法! 原本使用save时是没有问题了,改成saveOrUpdate 用了一下就报错了。 com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: error: can not execut

    2024年02月11日
    浏览(40)
  • MySQL的IF语句详解

    MySQL数据库中,IF语句是一种条件控制语句,用于根据某些条件的真假来执行不同的代码逻辑。IF语句可以帮助我们在SQL查询中实现更复杂的逻辑操作。 1、IF语句的基本用法 IF(condition, true_statement, false_statement); condition: 条件表达式,可以是任何返回布尔值的表达式。 true_state

    2024年02月03日
    浏览(37)
  • 一篇文章带你了解-selenium工作原理详解

    前言 Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。 主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得

    2024年02月10日
    浏览(53)
  • MYSQL-SELECT语句超详解

    目录 前言: SELECT语法 示例 单个字段查询 多个字段查询 查询所有字段 没有FROM的SELECT  查询系统时间 数值计算 虚拟表dual WHERE语句  示例 = AND OR 比较运算符 AND  OR  运算符优先级  IN  NOT IN  BETWEEN NOT BETWEEN LIKE EXISTS ORDER BY  LIMIT DISTINCT 前言: 示例中操作的表为 Sakila 示例数

    2024年02月12日
    浏览(70)
  • SQL UPDATE 语句(更新表中的记录)

    UPDATE 语句用于更新表中已存在的记录。 还可以使用AND或OR运算符组合多个条件。                 SQL UPDATE 语法 具有WHERE子句的UPDATE查询的基本语法如下所示:  请注意  更新表中的记录时要小心! 要注意SQL UPDATE 语句中的 WHERE 子句!   WHERE子句指定哪些记录需要更新。如

    2024年04月28日
    浏览(42)
  • SQL入门之第八讲——UPDATE更新语句

    定义:UPDATE更新语句是用来修改表中一条数据或者多条数据记录 基本语法: 1. 更新单行数据 实例1:在学生表中,将学生编号Sid为6的学生姓名Sname修改为:杨红梅 执行结果: SET后面除了带文本之外,还可以是数学表达式 实例2:在学生表中,将学生编号Sid为10的学生姓名对应

    2023年04月12日
    浏览(42)
  • 解决Oracle SQL语句性能问题——SQL语句改写(视图、标量子查询及update)

    我们在前述文章中也已经提到,对于高版本的关系库,尤其是针对Oracle这样的关系库,绝大多数场景下,同一语义和结果的SQL语句的具体语法,不会成为SQL语句执行计划的影响因素,但在少数场景下,针对同一语义和结果的SQL语句的不同写法,数据库优化器最终会分别为其生

    2024年02月10日
    浏览(47)
  • MySQL Select 查询语句详解及高级用法

    MySQL是一个开源的关系型数据库管理系统,支持多种操作语言,其中最基础、最常用的命令之一就是SELECT语句。在本篇文章中,这里将详细介绍MySQL SELECT语句的各个方面,从最基本的查询语句,到更高级的技巧和功能。 SELECT语句用于从表格中检索数据。其基本语法如下: sq

    2024年02月08日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包