暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL更新执行的过程

张芝 2024-08-13
35

Select语句的执行过程会经过连接器、分析器、优化器、执行器、存储引擎,同样的Update语句也会同样走一遍 Select语句的执行过程,但是和 elect最大不同的是,Update语句会涉及到两个日志的操作redo log(重做日志)和 binlog(归档日志)。


关键词:MySQL、Select语句、Update语句、redo log、binlog


本文作者:CSDN博主【程序猿进阶】



那么 Mysql中又是怎么使用redo log和binlog?为什么要使用redo log和binlog呢?直接执行更新然后存库不就行了吗?还要放在 redo log和 binlog中,这不是多此一举吗?且听我慢慢道来,这里面大有文章。


01  
redo log

大家都是知道 Mysql是关系型数据库,用来存储数据的,在访问数据库量大的时候,Mysql读写磁盘访问的效率是非常低的,加上sql中的条件对数据的筛选过滤,那么效率就更低了。这也是为什么引入非关系型数据库作为作为数据缓存原因,例如:Redis、MongoDB等,就是为了减少sql执行期间的数据库 io操作。

同样的道理,若是每次执行update语句都要进行磁盘 io操作、以及数据的过滤筛选,小量的访问和数据量数据库还可以撑住,那么访问量一大以及数据量一大,这样数据库肯定顶不住。基于上面的问题于是出现了redo log日志,redo log日志也叫做WAL技术(Write-Ahead Logging),他是一种先写日志,并更新内存,最后再更新磁盘的技术,并且更新磁盘往往是在 Mysql比较闲的时候,这样就大大减轻了Mysql的压力。

redo log的特点就是:redo log是固定大小,是物理日志,属于InnoDB引擎的,并且写 redo log是环状写日志的形式:


如上图所示:若是四组的redo log文件,一组为1G的大小,那么四组就是4G的大小,其中write pos是记录当前的位置,有数据写入当前位置,那么write pos就会边写入边往后移。而check point是擦除的位置,因为redo log是固定大小,所以当redo log满的时候,也就是write pos追上check point的时候,需要清除redo log的部分数据,清除的数据会被持久化到磁盘中,然后将check point向前移动。redo log日志实现了即使在数据库出现异常宕机的时候,重启后之前的记录也不会丢失,这就是crash-safe能力。


02  
binlog

binlog称为归档日志,是逻辑上的日志,它属于Mysql Server层面的日志,记录着sql的原始逻辑,主要有两种模式,一个是statement格式记录的是原始的sql,而row格式则是记录行内容。那么这样看来redo log和binlog虽然记录的形式、内容不同,但是这两者日志都能通过自己记录的内容恢复数据,那么为什么还要这两个日志同时存在呢?只要其中一个不就行了嘛,两个同时存在不就多此一举了嘛。且听我慢慢道来,这里面也大有文章。

因为刚开Mysql自带的引擎 MyISAM就没有crash-safe功能的,并且在此之前Mysql还没有InnoDB引擎,Mysql自带的binlog日志只是用来归档日志的,所以InnoDB引擎也就通过自己redo log日志来实现crash-safe功能。


03  
update执行过程

上面说了那么久两种日志的作用和特点,那么这两种日志究竟和update执行语句有什么关系呢?先来看图:


前提:当前的引擎是使用InnoDB,update语句与select语句区别主要是这两日志的使用主要是在执行器和引擎之间进行交互时体现的区别。假如执行如下一条简单的更新语句是:

    update user set age=age+1 where id =2;
    复制

    上面说过 select语句走过的流程 update语句也会走一遍,当来到执行器的时候:
    1. 执行器会调用引擎的读接口,然后找到id=2的数据行,因为id是主键索引,索引按照树的搜索找到这一行,若是数据行已经存在于内存的数据页中就会立即将结果返回,若是不在内存中,就会从磁盘中进行加载到内存中,然后将查询的结果返回。
    2. 执行器将返回的结果的age字段+1,并调用引擎的写接口写入更新后的数据行。
    3. 引擎获取到更新后的数据行更新到内存和redo log(也是写入磁盘,顺序写入,比较快)中,并告诉执行器可以随时提交事务,此时的redo log处于prepare阶段。
    4. 执行器收到引擎的告知后,生成binlog日志,并且调用引擎的接口提交事务,引擎将redo log的状态修改为commit状态,这样这个更新操作算是完成。
    「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
    关注作者
    【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论