「原创」从RedoLog和BinLog聊到一条Update语句的执行

点击上方“后端开发技术”,选择“设为星标” ,质资源及时送达「原创」从RedoLog和BinLog聊到一条Update语句的执行

本文内容:从binlog 和 redo log的详细讲解,引出一条Update语句在MySQL中详细的执行流程,面试重点内容!

Redo log 重做日志

我们知道,在MySQL写入数据的时候,有可能是追加数据,也有可能是定位到一条已经存在的数据去修改。对于磁盘的随机读写来说,这个速度是比较慢的,无法满足高IO操作的场景。为了提高写入效率,我们可以先写到内存中,有空的时候再去写入磁盘。

但是这样会产生一个问题:内存中的数据并没有持久化,如果断电数据不就丢失了?

为了解决数据丢失问题,我们引入了 redo log(重做日志)来解决这个问题。先写入redo log ,再去磁盘写入数据,这就是WAL(Write-Ahead Logging),一种在对与非内存数据库提高IO效率的常用做法。这样就可以在 crash 的情况下依赖 log 去恢复数据,保证了数据的持久性。

Write-Ahead Logging 预写式日志记录

数据库中一种高效的日志算法,对于非内存数据库而言,磁盘I/O操作是数据库效率的一大瓶颈。在相同的数据量下,采用WAL日志的数据库系统在事务提交时,磁盘写操作只有传统的回滚日志的一半左右,大大提高了数据库磁盘I/O操作的效率,从而提高了数据库的性能。

WAL 的优点

  1. 读和写可以完全地并发执行,不会互相阻塞(但是写之间仍然不能并发)。
  2. WAL 在大多数情况下,拥有更好的性能(因为无需每次写入时都要写两个文件)。
  3. 磁盘 I/O 行为更容易被预测。
  4. 使用更少的 fsync()操作,减少系统脆弱的问题。

redo log 实现

让我们看看 MySQL 真正是如何做的。

当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log 里面,并更新内存。在适当的时候,比如磁盘空闲, redo log 中的数据会刷到磁盘中。

在InnoDB 引擎中 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么一共就可以记录 4GB 的操作。write pos 是当前记录的位置,一边写一边移动,checkpoint 标记着当前要擦除的位置,擦除记录前要把记录更新到数据文件,同样边擦边往一个方向移动。如果warite pos 写完最后一个文件,会移动到 ib-log-file-0 重新开始写入。

「原创」从RedoLog和BinLog聊到一条Update语句的执行

如果 write pos 追上 checkpoint,表示 redo log 满了,这时候不能再执行新的更新,得停下来先擦掉一些数据,并且把数据同步落到磁盘,再把 check point 往前推进。

查看 redo log 参数

每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组至少有2个重做日志文件,默认为 ib-log-file-0 和 ib-log-file-1 。

show variables like '%innodb_log%';

关键词 :循环写、WAL、先写日志再写数据

Bin Log 归档日志

redo log 作为 InnoDB 引擎的特有日志,可以保证数据的安全性,但是其他引擎如何记录数据日志呢?在 Server 层,MySQL 有自己的日志 bin log(归档日志)。大家一定要将MySQL拆开看,MySQL = Server + 不同数据存储引擎,并非一个整体。

Binlog记录所有MySQL数据库表结构变更以及表数据修改的二进制日志,不会记录select和show这类查询操作的日志。Binlog日志是以事件形式记录,还包含语句所执行的消耗时间。开启Binlog日志有以下两个最重要的使用场景。

  • 主从复制:在主库中开启Binlog功能,这样主库就可以把Binlog传递给从库,从库拿到Binlog后实现数据恢复达到主从数据一致性。
  • 数据恢复:通过mysqlbinlog等工具来恢复数据

Binlog文件记录模式有STATEMENT、ROW和MIXED三种,通常使用 row 模式。


为什么有两份日志

在 MySQL 最开始是没有 InnoDB 引擎的,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有应对故障恢复数据的能力,binlog 日志只能用于归档。InnoDB 是后来以插件形式加入,所以它自己实现了一套日志系统以保障数据安全,应对 crash recovery。


bin log 与 redo log 区别

这里我主要总结了5点内容

  1. 内容不同:redo log 是物理日志,内容基于磁盘的Page,binlog的内容是二进制的,根据 binlog_format 参数的不同,可能基于sql语句、基于数据本身或者二者的混合。
  2. 层次不同:redo log 作用于 InnoDB与引擎,bin log 位于MySQL Server 层,可供所有引擎使用
  3. 磁盘存贮形式不同:redo log 循环写,bin log 不断累加,所以可以用做数据恢复或主从同步
  4. 写入时机不同:binlog在事务通常提交时写入或者N个事务提交一次,redo log的写入时机相对多元,可能每次事务提交时,也可能被其他线程事务提交,还可能每秒钟刷盘。(注意:redolog未提交的事务也可能刷入磁盘)
  5. 作用不同:redo log是用于crash recovery的,保证MySQL宕机也不会影响持久性;binlog是用于point-in-time recovery的,保证服务器可以基于时间点恢复数据,此外binlog还用于主从复制。

两阶段提交

因为 redo log 在InnoDB层,bin log 在Server层,这就引入了一个新问题。

如果写入 redo log 成功,bin log写入磁盘前crash,此时事务还没有没提交,此时 redo log 中新写入到数据是无效的。重新起动数据库进行数据恢复,将 redo log 中的数据恢复到磁盘中,这就产生了无效数据。

对于这种情况,聪明的你肯定知道,要引入两阶段提交。第一阶段 redo log 写入数据,处于 prepare 状态,等待Server层保存bin log 数据落盘后,事务提交的同时提交 redo log,使 redo log 变为commit状态,这样就保证了 redo log 数据和 bin log 数据的一致性。


一条Update语句的执行

有了前面的知识,现在可以探究下update语句在MySQL中是如何执行的。假设现在执行SQL :update table_test set a=a+1 where id=2;

「原创」从RedoLog和BinLog聊到一条Update语句的执行
  1. 首先通过客户端通过连接器连接、判断权限。
  2. 验证通过后SQL经过分析器进行词法和语法分析(AST),如果是Update语句,mysql 会把查询表 table_test 的所有查询缓存全部清空。(由此可以看出,并不建议开启查询缓存)
  3. 优化器对验证后的SQL进行优化,计划匹配id索引,生成执行计划。
  4. 执行器拿到最终SQL,调用对应存储引擎的接口开始执行update sql。
  5. InnoDB引擎开启事务,执行引擎先从内存中查询是否存在id=2的数据,如果匹配到则把对应的数据的 a 字段+1,然后保存到内存中;如果没有查询到id=2的数据则会去磁盘中查询,查询的时候会以页为单位把数据读取到内存中,然后更新,保存到内存中。
  6. 在第5步保存更新数据前,InnoDB 引擎会把数据行保存到 redo log 中,此时 redo log 为预提交状态,通知Server的执行器准备就绪,随时可以提交事务。
  7. 执行器会生成对应的bin log,并且写入磁盘。
  8. 提交事务,此时redo log 才会commit。到这里才意味着一个事务的执行完成。

最后,欢迎大家提问和交流。


如果觉得对你有帮助,欢迎点赞分享,感谢阅读!

「原创」MySQL事务原理也想问倒我?!附2022最新面试题

2022-06-01

「原创」从RedoLog和BinLog聊到一条Update语句的执行

「必备」破解IDEA工具,就特么差你收藏了!

2022-05-28

「原创」从RedoLog和BinLog聊到一条Update语句的执行

5分钟学会MySQL双主双从架构和Mycat读写分离搭建

2022-05-26

「原创」从RedoLog和BinLog聊到一条Update语句的执行

快速深入理解JDK动态代理原理

2022-05-19

「原创」从RedoLog和BinLog聊到一条Update语句的执行


原文始发于微信公众号(后端开发技术):「原创」从RedoLog和BinLog聊到一条Update语句的执行

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/46957.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!