MySQL学习笔记

MySQL日志binlog、redolog、undolog

2021-09-16  本文已影响0人  想象之中丶意料之外

本文主要总结下重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)的概念。

crash-safe概念

InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。

举个列子:当我们修改的时候,写完内存了(buffer),但数据还没真正写到磁盘的时候。此时我们的数据库挂了,我们可以对数据进行恢复

redo log (重做日志)

redo log 是物理日志,记载着每次在某个页上做了什么修改。写redo log也是需要写磁盘的,但它的好处就是顺序IO(我们都知道顺序IO比随机IO快非常多)。写入的速度很快

生命周期

  1. 事务开始之后,就开始产生 redo log 日志了,在事务执行的过程中,redo log 开始逐步落盘
  2. 当对应事务的脏页写入到磁盘之后,redo log 的使命就完成了,它所占用的空间也就可以被覆盖了。
  3. InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB。从头开始写,写到末尾就又回到开头循环写
file
  1. write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。
  2. write pos 和 checkpoint 之间的的部分,可以用来记录新的操作。如果 write pos 追上 checkpoint,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。

存储内容

redo log 包括两部分:

落盘方式(将 innodb 日志缓冲区的日志刷新到磁盘)

  1. Master Thread 每秒一次执行刷新 Innodb_log_buffer 到重做日志文件
  2. 每个事务提交时会将重做日志刷新到重做日志文件
  3. 当重做日志缓存可用空间少于一半时,重做日志缓存被刷新到重做日志文件

注意:

  1. 其实写redo log的时候,也会有buffer,是先写buffer,再真正落到磁盘中的。至于从buffer什么时候落磁盘,会有配置供我们配置。
  2. redo log 是 InnoDB 引擎特有的日志
  3. 持久性就是靠redo log来实现的(如果写入内存成功,但数据还没真正刷到磁盘,如果此时的数据库挂了,我们可以靠redo log来恢复内存的数据,这就实现了持久性)。

undo log (回滚日志)

生命周期

  1. 事务开始之前,将当前事务版本生成 undo log,undo log 也会产生 redo log 来保证 undo log 的可靠性。
  2. 事务提交之后,undo log 并不能立马被删除,而是放入待清理的链表
  3. purge 线程判断是否有其它事务在使用 undo 段中表的上一个事务之前的版本信息,从而决定是否可以清理 undo log 的日志空间。

存储内容

undo log 存储的是逻辑格式的日志,保存了事务发生之前的上一个版本的数据,可以用于回滚。当一个旧的事务需要读取数据时,为了能读取到老版本的数据,需要顺着 undo 链找到满足其可见性的记录。

存储位置

默认情况下,undo 文件是保存在共享表空间的,也即 ibdatafile 文件中,当数据库中发生一些大的事务性操作的时候,要生成大量的 undo log 信息,这些信息全部保存在共享表空间中,因此共享表空间可能会变得很大,默认情况下,也就是 undo log 使用共享表空间的时候,被“撑大”的共享表空间是不会、也不能自动收缩的。因此,MySQL5.7 之后的“独立 undo 表空间”的配置就显得很有必要了。

binlog (二进制日志)

bin-log三种模式

Statement 模式

每一条修改数据的 sql 都会记录到 master 的 binlog 中,slave 在复制的时候,sql 进程会解析成和原来在 master 端执行时的相同的 sql 再执行。

Row 模式

日志中会记录每一行数据被修改的形式,然后在 slave 端再对相同的数据进行修改。row 模式只记录要修改的数据,只有 value,不会有 sql 多表关联的情况。

Mixed 模式

从官方文档中看到,之前的 MySQL 一直都只有基于 statement 的复制模式,直到 5.1.5 版本的 MySQL 才开始支持 row 复制。从 5.0 开始,MySQL 的复制已经解决了大量老版本中出现的无法正确复制的问题。但是由于存储过程的出现,给 MySQL Replication 又带来了更大的新挑战。另外,看到官方文档说,从 5.1.8 版本开始,MySQL 提供了除 Statement 和 Row 之外的第三种复制模式:Mixed,实际上就是前两种模式的结合。在 Mixed 模式下,MySQL 会根据执行的每一条具体的 SQL 语句来区分对待记录的日志形式,也就是在 statement 和 row 之间选择一种。新版本中的 statment 还是和以前一样,仅仅记录执行的语句。而新版本的 MySQL 也对 row 模式做了优化,并不是所有的修改都会以 row 模式来记录,比如遇到表结构变更的时候就会以 statement 模式来记录,如果 SQL 语句确实就是 update 或者 delete 等修改数据的语句,那么还是会记录所有行的变更。

生命周期

事务提交的时候,一次性将事务中的 sql 语句(一个事务可能对应多个 sql 语句)按照一定的格式记录到 binlog 中,这里与 redo log 很明显的差异就是 redo log 并不一定是在事务提交的时候才刷新到磁盘,而是在事务开始之后就开始逐步写入磁盘。binlog 的默认保存时间是由参数 expire_logs_days 配置的,对于非活动的日志文件,在生成时间超过 expire_logs_days 配置的天数之后,会被自动删除。

binlog和redo log 写入的细节 - 两阶段提交

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

update t set c = c+1 where id=2;

这里我给出这个 update 语句的执行流程图,图中浅色框表示是在 InnoDB 内部执行的,深色框表示是在执行器中执行的


file

附:

image

转【彻底搞懂mysql日志系统binlog,redolog,undolog

上一篇 下一篇

猜你喜欢

热点阅读