(面经总结)一篇文章带你学习 Mysql 里的 binlog、redo log 和 undo log

一、binlog

1. 什么是 binlog

binlog 记录了数据库表结构和表数据变更,比如update/delete/insert/truncate/create。它不会记录 select(因为这没有对表没有进行变更)

binlog 我们可以简单理解为:存储着每条变更的SQL语句(当然从下面的图看来看,不止SQL,还有XID「事务Id」等等)
在这里插入图片描述

2. 作用

主要有两个作用:复制和恢复数据

  • MySQL在公司使用的时候往往都是一主多从结构的,从服务器需要与主服务器的数据保持一致,这就是通过binlog来实现的
  • 数据库的数据被干掉了,我们可以通过 binlog 来对数据进行恢复

因为 binlog 记录了数据库表的变更,所以我们可以用 binlog 进行复制(主从复制)和恢复数据

二、redo log

1. 什么是 redo log

假设我们有一条 sql 语句:

update user_table set name='java3y' where id = '3';

MySQL执行这条SQL语句,肯定是先把id=3的这条记录查出来,然后将name字段给改掉。这没问题吧?

实际上 Mysql 的基本存储结构是页(记录都存在页里边),所以 MySQL 是先把这条记录所在的页找到,然后把该页加载到内存中,将对应记录进行修改

现在就可能存在一个问题:如果在内存中把数据改了,还没来得及落磁盘,而此时的数据库挂了怎么办?
显然这次更改就丢了。
在这里插入图片描述
如果每个请求都需要将数据立马落磁盘之后,那速度会很慢,MySQL 可能也顶不住。所以 MySQL 是怎么做的呢?

MySQL引入了 redo log,内存写完了,然后会写一份 redo log,这份 redo log 记载着这次在某个页上做了什么修改

在这里插入图片描述
其实写 redo log 的时候,也会有 buffer,是先写 buffer,再真正落到磁盘中的。至于从 buffer 什么时候落磁盘,会有配置供我们配置。
在这里插入图片描述
写 redo log 也是需要写磁盘的,但它的好处就是顺序 IO(我们都知道顺序IO比随机IO快非常多)

顺序IO:读写操作的访问地址连续,所以磁道搜索时间显著减少
随机IO:读写操作时间连续,但访问地址不连续,随机分布在磁盘的地址空间中

存在作用:

所以,redo log的存在为了:当我们修改的时候,写完内存了,但数据还没真正写到磁盘的时候。此时我们的数据库挂了,我们可以根据 redo log 来对数据进行恢复

保持了数据库中的持久性

因为 redo log是顺序IO,所以写入的速度很快,并且 redo log 记载的是物理变化(xxxx页做了xxx修改),文件的体积很小,恢复速度很快

主要作用:持久性、提升性能

提升性能:原先为了保持一致性,每次事务提交成功,就会将该事物涉及到的数据页全部刷新到磁盘中,这会出现两个问题,一个是因为数据库是以页为单位和磁盘交互,一个事务可能只修改一个数据页里的几个字节,,这个时候将完整的数据页刷到磁盘的话,太浪费资源了!另一个问题就是一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!
所以就可以引入redo log,磁盘刷新采用异步方式,用redo log记录修改内容
原因:缓存,顺序IO

2. redo log 和 binlog 的区别

都是用作恢复,但是区别还是挺大的

(1)存储的内容

binlog 记载的是update/delete/insert这样的SQL变更语句,而 redo log 记载的是物理修改的内容(xxxx页修改了xxx)

简单来说就是:redo log 记录的是数据的物理变化,binlog 记录的是数据的逻辑变化

(2)功能

redo log 的作用是为持久化而生的。写完内存,如果数据库挂了,那我们可以通过redo log来恢复内存还没来得及刷到磁盘的数据,将redo log加载到内存里边,那内存就能恢复到挂掉之前的数据了。

binlog的作用是复制和恢复而生的。

  • 主从服务器需要保持数据的一致性,通过 binlog 来同步数据。
  • 如果整个数据库的数据都被删除了,binlog 存储着所有的数据变更情况,那么可以通过 binlog 来对数据进行恢复。

又看到这里,你会想:”如果整个数据库的数据都被删除了,那我可以用redo log的记录来恢复吗?“

不能

因为功能的不同,redo log 存储的是物理数据的变更,如果我们内存的数据已经刷到了磁盘了,那redo log 的数据就无效了。所以 redo log 不会存储着历史所有数据的变更,文件的内容会被覆盖的。

(3)写入的细节

redo log 是MySQL的 InnoDB 引擎所产生的

binlog无论MySQL用什么引擎,都会有的。

redo log 事务开始的时候,就开始记录每次的变更信息,而 binlog 是在事务提交的时候才记录

于是新有的问题又出现了:我写其中的某一个 log,失败了,那会怎么办?

现在我们的前提是先写 redo log,再写 binlog,我们来看看:

  • 如果写 redo log 失败了,那我们就认为这次事务有问题,回滚,不再写 binlog。
  • 如果写 redo log 成功了,写 binlog,写 binlog 写一半了,但失败了怎么办?我们还是会对这次的事务回滚,将无效的 binlog 给删除(因为binlog会影响从库的数据,所以需要做删除操作)
  • 如果写 redo log 和 binlog 都成功了,那这次算是事务才会真正成功。

简单来说:MySQL需要保证 redo log 和 binlog 的数据是一致的,如果不一致,那就乱套了。

  • 如果redo log写失败了,而binlog写成功了。那假设内存的数据还没来得及落磁盘,机器就挂掉了。那主从服务器的数据就不一致了。(从服务器通过binlog得到最新的数据,而主服务器由于redo log没有记载,没法恢复数据)
  • 如果redo log写成功了,而binlog写失败了。那从服务器就拿不到最新的数据了。

MySQL 通过两阶段提交来保证 redo log 和 binlog 的数据是一致的

  • 阶段1:InnoDB redo log 写盘,InnoDB 事务进入 prepare 状态
  • 阶段2:binlog 写盘,InooDB 事务进入 commit 状态

每个事务 binlog 的末尾,会记录一个 XID event,标志着事务是否提交成功,也就是说,恢复过程中,binlog 最后一个 XID event 之后的内容都应该被清除
在这里插入图片描述

三、undo log

undo log 主要有两个作用:回滚和多版本控制(MVCC)

在数据修改的时候,不仅记录了redo log,还记录 undo log,如果因为某些原因导致事务失败或回滚了,可以用 undo log 进行回滚

保证了原子性:一个事务包含多个操作,这些操作要么全部执行,要么全都不执行

undo log 主要存储的也是逻辑日志,比如我们要 insert 一条数据了,那 undo log 会记录的一条对应的delete 日志。我们要 update 一条记录时,它会记录一条对应相反的 update 记录。

因为 undo log 存储着修改之前的数据,相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行了

所以 undo log 也是隔离性实现的基础

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值