简单聊聊MySQL的三大日志(Redo Log、Binlog和Undo Log)各有什么区别

2024年 3月 15日 75.8k 0

在管理MySQL数据库时,了解和区分数据库使用的三大日志类型至关重要。这些日志对于确保数据的完整性、提供恢复机制以及维持数据库的稳定性发挥着关键作用。最主要还是小豆前段时间去参加面试被问到了这些内容,下面将详细讨论Redo Log、Binlog和Undo Log的异同。

Redo Log(重做日志)

  • 作用:Redo Log主要用于保证事务的持久性和数据库的崩溃恢复能力。当数据库发生崩溃时,InnoDB存储引擎可以使用Redo Log来恢复未提交事务的数据,确保数据的一致性。
  • 内容:在事务处理中产生的所有数据页的物理修改,比如数据页的变动。它包括内存中的Redo Log Buffer和磁盘上的Redo Log File。
  • 写入时机:在事务执行过程中,数据的更改首先被写入Redo Log Buffer,然后在事务提交时,这些更改会被写入到Redo Log File中。这个过程保证了MySQL可以在系统意外重启后,按照事务提交前的状态重新构建数据页,进而实现持久性。

Binlog(二进制日志)

  • 作用:Binlog主要用于数据复制(主从复制)和数据恢复。它记录了所有修改了数据库状态的SQL语句,比如实际执行的SQL语句。使得可以在主从复制环境中同步数据,或者在数据丢失后进行恢复。
  • 内容:Binlog记录了逻辑操作,如SQL语句。它以二进制的形式保存,并且可以是三种格式之一:Statement(记录SQL语句)、Row(记录行级更改)或Mixed(两者结合)。
  • 写入时机:在事务提交时,Binlog会记录本次修改的数据。Binlog的写入通常在Redo Log之后,以确保数据的一致性。

Undo Log(回滚日志)

  • 作用:Undo Log主要用于实现事务的原子性和隔离性。它记录了事务所做的更改,以便在事务失败或需要回滚时,可以恢复到事务开始之前的状态。
  • 内容:Undo Log记录了数据被修改前的样子,以及事务的回滚信息。它允许数据库在读取旧版本的数据时,能够提供一致的视图。
  • 写入时机:在数据被修改时,Undo Log会同时记录原始数据。在事务回滚或需要通过MVCC读取旧数据版本时,Undo Log会被使用。

日志之间的关系

Redo LogUndo Log是InnoDB存储引擎紧密关联的组成部分,其中Redo负责记录事务的前景操作,Undo负责记录事务的后景操作。而Binlog记录了执行修改的SQL语句,这三者协同工作保障了事务的ACID特性。Redo和Undo日志通常存在于存储引擎层面,而Binlog则是MySQL数据库级别的记录。

  • Redo Log是InnoDB特有的,专门记录物理更改,用于保证数据的持久性和崩溃恢复。
  • Binlog是MySQL服务器层面的,记录逻辑更改,用于主从复制和数据恢复,记录逻辑操作。
  • Undo Log也是InnoDB特有的,记录数据改变前的状态,用于事务的回滚和多版本并发控制(MVCC)。

日志写入流程

以一次事务执行为例,使用流程图画一下日志写入流程:

sequenceDiagram
    participant 用户
    participant 事务 as 事务
    participant Undo Log
    participant Redo Log Buffer
    participant Redo Log File
    participant Binlog Buffer
    participant Binlog File
    participant 磁盘文件

    用户->>事务: 开始事务
    Note over 事务: 执行数据修改操作
    事务->>Undo Log: 记录修改前的状态
    事务->>Redo Log Buffer: 记录修改的内容
    Note over 事务: 更改暂存于缓冲中
    事务->>事务: 数据操作完成
    事务->>Redo Log Buffer: 准备提交
    Redo Log Buffer-->>Redo Log File: 同步写入日志
    Note over Redo Log File: 日志已持久化
    事务->>Binlog Buffer: 记录事务日志
    事务->>用户: 开始事务提交流程
    用户->>事务: 发送COMMIT命令
    事务->>Redo Log File: 确认日志已写入
    Binlog Buffer-->>Binlog File: 同步写入日志
    事务->>磁盘文件: 应用更改
    Note over 磁盘文件: 数据修改最终确定
    事务->>用户: 事务提交成功
    事务->>事务: 结束事务

在这个流程图中,我们描述了以下步骤:

  • 用户通过执行START TRANSACTIONBEGIN或者DML语句发起一个事务。
  • 事务执行数据修改,同时记录到Undo Log(记录修改前的状态)和Redo Log Buffer(记录修改的内容)。
  • 事务数据预写入内存中的Redo Log Buffer,为提交做好准备,但这是临时的。
  • 事务完成所有操作。
  • 事务提交时,Redo Log Buffer中的内容被写入到磁盘上的Redo Log File,确保数据的持久性。
  • 同时,事务的更改被记录到Binlog Buffer,为复制和数据恢复做准备。
  • 执行COMMIT命令,请求提交事务。
  • 在提交时,事务确保Redo Log Buffer和Binlog Buffer中的更改都已同步到各自的磁盘文件。
  • 事务将修改最终应用到磁盘文件,完成数据的持久化。
  • 返回事务提交成功的确认给用户。
  • 其他问题

    1、会不会出现数据库磁盘中的文件已经被修改,但是没有记录到binlog日志中的情况?

    通常情况下,这种情况是不会发生的。因为数据库在执行写操作的时候,会先将操作记录在Binlog中,然后再修改磁盘中的对应数据库文件。这就是所谓的write-ahead logging(WAL,预写式日志),即修改磁盘中的文件之前,必须先将相关的操作信息写入日志。

    数据库维护了一个缓冲区,当有数据需要写入磁盘时,首先将这些数据写入缓冲区,然后再由缓冲区将这些数据批量写入磁盘,这样可以提高数据写入磁盘的效率。

    而缓冲区在将数据写入磁盘之前,必须先将相关的操作信息写入日志。也就是说,任何修改磁盘中文件的操作,必须先写入日志。只有在日志成功写入后,缓冲区的数据才能写入硬盘。这种机制保证了在数据库系统崩溃的情况下,可以通过重放日志来恢复数据,确保数据的最终一致性和原子性。

    至于你提到的这种情况,可能是由于些别的情况,比如操作系统崩溃,数据库软件的bug等等,导致数据已经写入了磁盘但是日志还没有来得及写入。但是这种情况在正常操作下是非常少见的,一般只会在极端的情况下才会发生。

    2、事务提交前直接把数据写入磁盘就能保证持久性,为什么还要用redo log呢?

    1、性能问题,直接写入磁盘(随机写)的性能通常比顺序写入要差。直接写入磁盘是随机写入。而Redo Log通常是顺序写入的,这可以提高写入效率。

    2、原子性,如果在将数据写入磁盘的过程中发生系统崩溃(如电源故障、硬件故障等),那么可能只有部分数据被写入,导致数据不一致。Redo Log通过记录事务所做的修改,可以在故障后重做这些操作,确保事务的原子性。

    3、并发问题,在高并发环境下,如果每个事务都直接写入磁盘,那么在多个事务同时修改同一条记录时,可能会出现冲突。Redo Log通过记录事务所做的修改,可以在事务提交时快速完成,而不需要对数据行进行长时间的锁定。

    相关文章

    Oracle如何使用授予和撤销权限的语法和示例
    Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
    下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
    社区版oceanbase安装
    Oracle 导出CSV工具-sqluldr2
    ETL数据集成丨快速将MySQL数据迁移至Doris数据库

    发布评论