MySQL日志可以用来干啥?

了解MySQL的童靴们都知道,MySQL有好几种日志——undo log(回滚日志)redo log(重做日志)还有binlog(归档日志),为啥需要这么多日志?这些日志分别都是干啥用的?在进一步探讨这么些问题之前,我们需要先了解一下一条SQL语句的执行过程

查询语句执行流程(来源小林coding)

笔者作为一名初学小白,时常感到好奇:当执行了 SQL 语句对数据记录进行修改时,如果突然遭遇系统关机、服务器卡死等故障,这段记录修改该如何是好?

小伙伴们可能会不假思索地回答:“通过事务回滚恢复到执行增删改之前的状态!” 没错,这确实是 MySQL 保障数据安全的重要机制之一。即使我们没有显式地开启事务和提交事务,MySQL 也会隐式地启动事务执行“增删改”语句,并在执行完后自动提交事务(MySQL 默认开启了 autocommit 参数)。

但你是否想过,MySQL 是如何实现这种“时光倒流”般的神奇操作的呢?这就要归功于 MySQL 的“时光机”—— undolog、redolog 和 binlog。它们就像数据库的“守护天使”,默默地记录着数据的每一次变化,在关键时刻挺身而出,保障数据的安全性和一致性。

undolog、redolog 和 binlog 是 MySQL 保障数据安全的三大利器,它们各司其职,共同构建了 MySQL 强大的数据保护机制:

  • undolog :负责事务的原子性和 MVCC,确保数据的一致性。
  • redolog :负责事务的持久性,确保数据不会因故障而丢失。
  • binlog :负责数据的备份和主从复制,确保数据的可靠性和高可用性。

接下来,我们来进一步探讨这三种日志如何实现数据库神操作。

Undo Log 是干啥的

在前言我们提到,MySQL 会隐式开启事务执行“增删改”语句,当操作过程中发生崩溃时,事务会进行回滚。那么,回滚操作中旧的数据要从哪里来呢?

想象一下,如果在执行“增删改”操作之前,我们将要操作的数据记录做一个备份,那么当我们想恢复到执行操作之前的状态时,只要对照备份的信息就可以了。

当然,每次执行操作都要进行备份会很麻烦,但我们可以根据需求进行相应的操作记录。例如:

  • 执行删除操作之前,记录要删除的记录信息,若想恢复,我们再把记录插回去;
  • 执行新增操作之前,记下新增记录的ID,撤销新增只需要把对应ID记录删除即可;
  • 执行修改操作之前,记录修改前的数据,撤销修改时只需将数据恢复到修改前的状态。

这种记录操作前数据的方式,正是 MySQL 中 Undo Log (回滚日志)的核心思想。Undo Log 记录了事务执行过程中对数据的修改操作,用于在事务回滚时撤销这些修改,将数据恢复到事务开始前的状态,它保证了事务的ACID特性中的原子性

undo log 是一种用于撤销回退的日志。在事务没提交之前,MySQL 会先记录更新前的数据到 undo log 日
志文件里面,当事务回滚时,可以利用 undo log 来进行回滚。如下图:

image-20240917225450255

每当 InnoD8 引擎对一条记录进行操作(修改、删除、新增)时,要把回滚时需要的信息都记录到 undo log 里,发生回滚时,就读取undo log日志记录的数据,执行相反的操作来完成数据恢复。

需要注意的是,不同的操作,因需求不同,其undo log格式也不同,此处仅以更新操作的日志为例。每条记录的每一次更新操作产生的 Undo Log 格式中,都包含一个 roll_pointer 指针和一个 trx_id 事务 ID:

  • trx_id 事务 ID:用于标识该记录是被哪个事务修改的,帮助系统追踪事务的执行顺序。
  • roll_pointer 指针:将这些 Undo Log 串成一个链表,这个链表就被称为版本链。版本链记录了该记录的所有历史版本,使得系统可以在需要时回滚到任意一个历史状态。

版本链的结构如下图所示:

image-20240917232010721

另外,Undo Log 通过 ReadView + Undo Log 实现 MVCC(多版本并发控制)

对于「读提交」和「可重复读」隔离级别的事务:

  • 「读提交」:每次 SELECT 生成新的 Read View,可能导致同一事务中多次读取同一条数据时结果不一致。
  • 「可重复读」:事务启动时生成 Read View,并在整个事务期间使用,确保读取的数据一致。

这两个隔离级别通过「事务的 Read View 里的字段」和「记录中的隐藏列(trx_idroll_pointer)」进行比对,如果不满足可见性条件,就会顺着 Undo Log 版本链找到满足其可见性的记录,实现 MVCC。

因此,Undo Log 的两大作用是:

  1. 实现事务回滚,保障事务的原子性:在事务处理过程中,如果出现错误或用户执行 ROLLBACK 语句,MySQL 可以利用 Undo Log 中的历史数据将数据恢复到事务开始之前的状态。
  2. 实现 MVCC(多版本并发控制)的关键因素之一:MVCC 通过 ReadView + Undo Log 实现。Undo Log 为每条记录保存多份历史数据,MySQL 在执行快照读(普通 SELECT 语句)时,会根据事务的 Read View 里的信息,顺着 Undo Log 的版本链找到满足其可见性的记录。

Buffer Poll是干啥的

【更新中。。。】