HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
  • 《LearnJavaToFindAJob》

    • 导读

    • 【初级】6~12k档

    • 【中级】12k-26k档

      • JVM进阶

      • Java进阶

      • MySQL

        • Innodb和MyISAM索引的区别
        • MySQL一些索引失效的场景和原理
        • MySQL如何行转列?
        • MySQL的架构和执行流程
        • MySQL的自增ID用完了会怎样?
        • MySQL索引的分类、何时使用、何时不使用、何时失效?
        • MySQL联合索引在B+数的存储结构和最左匹配原则原理
        • Mysql的索引和主键的区别
        • binlog、redolog、undolog的区别和作用
        • 什么是前缀索引,什么情况才使用?
        • 可重复读是否能解决幻读?
        • 我以为我对Mysql事务很熟,直到我遇到了阿里面试官
        • 聊聊MySQL索引的分类和结构吧
      • 中间件

      • 算法

      • 高阶

    • 【高级】26k+档

    • 大厂面试题

    • 求职建议

    • 面经

  • LearnJavaToFindAJob
  • 【中级】12k-26k档
  • MySQL
#binlog #redolog #undolog #区别 #作用 #区别和作用
码农阿雨
2022-06-02
目录

binlog、redolog、undolog的区别和作用

我们知道事务有ACID四个,四个事务的实现是通过InnoDB日志和锁来保证的。

隔离性 主要通过数据库的锁机制(如行锁、表锁、间隙锁等)和 MVCC(多版本并发控制)来实现。

持久性 通过 redo log(重做日志)来实现

原子性 通过 undo log(回滚日志)来实现。

一致性:是事务的最终目标,由其他三个特性共同保证。

# 1. bin log

binlog 用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlog 是 mysql的逻辑日志,并且由 Server 层进行记录,使用任何存储引擎的 mysql 数据库都会记录 binlog 日志。

所以binlog日志并不是innodb独有的,它是server层的日志

既然是server层的日志,它记录的都是事务操作内容,是一种逻辑日志。

逻辑日志:可以简单理解为记录的就是sql语句 。

binlog 是通过追加的方式进行写入的,可以通过max_binlog_size 参数设置每个 binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。

# binlog使用场景:

  1. binlog可以作为恢复数据使用,通过使用 mysqlbinlog 工具来恢复数据。
  2. 主从复制搭建(数据同步)。在 Master 端开启 binlog ,然后将 binlog发送到各个 Slave 端, Slave 端重放 binlog 从而达到主从数据一致

# binlog刷盘时机:

MySQL数据库中的任何存储引擎对于数据库的更改都会产生binlog,此时记录还在内存中,那么 biglog是什么时候刷到磁盘中的呢?

  • 0:不去强制要求,由系统自行判断何时写入磁盘;
  • 1:每次 commit 的时候都要将 binlog 写入磁盘;
  • N:每N个事务,才会将 binlog 写入磁盘。

从上面可以看出, sync_binlog 最安全的是设置是 1 ,这也是MySQL 5.7.7之后版本的默认值。但是设置一个大一些的值可以提升数据库性能,因此实际情况下也可以将值适当调大,牺牲一定的一致性来获取更好的性能。

# binlog日志格式:

binlog 日志有三种格式,分别为 STATMENT 、 ROW 和 MIXED。

在 MySQL 5.7.7 之前,默认的格式是 STATEMENT , MySQL 5.7.7 之后,默认值是 ROW。日志格式通过 binlog-format 指定。

  • STATMENT:基于SQL 语句的复制( statement-based replication, SBR ),每一条会修改数据的sql语句会记录到binlog 中 。

    • 优点:不需要记录每一行的变化,减少了 binlog 日志量,节约了 IO , 从而提高了性能;
    • 缺点:在某些情况下会导致主从数据不一致,比如执行sysdate() 、 slepp() 等 。
  • ROW:基于行的复制(row-based replication, RBR ),不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了。

    • 优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题 ;
    • 缺点:会产生大量的日志,尤其是alter table 的时候会让日志暴涨
  • MIXED:基于STATMENT 和 ROW 两种模式的混合复制(mixed-based replication, MBR ),一般的复制使用STATEMENT 模式保存 binlog ,对于 STATEMENT 模式无法复制的操作使用 ROW 模式保存 binlog

# 2. redo log

redo log 是 InnoDB 引擎特有的。redo log作为异常宕机或者介质故障后的数据恢复使用。所以这也是持久性的依赖,只要事务提交成功,数据库对已经修改的数据就被永久保存下来了。

# 有了binglog为什么还要有redolog?

主要原因如下:

  1. binlog会记录所有的日志,是关于一个事务的逻辑日志,而redolog只需要记录innodb引擎本身的日志
  2. innodb是以页为单位和磁盘进行交互的,如果一个事务只修改一个数据页里面的几个字节,那将整个数据页刷盘就很浪费资源了;或者一个事务可能涉及修改多个数据页,而且binlog是随机写,如果每次事务提交都刷盘,会极大影响数据库的性能。
  3. 确保事务的持久性,如果binlog在刷盘的时候宕机了,就真的丢失了(当然binlog可以每次都刷盘但是性能不好),redo log的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入 redo log buffer中,所以在恢复的时候,redolog依然记录了宕机前的数据。

因此设计了redolog, 具体来说就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)。

# redo log 概念

redo log记录的是新数据的备份。在事务提交前,只要将redo log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是redo log已经持久化。系统可以根据redo log的内容,将所有数据恢复到最新的状态。 (从而达到持久性)

# redo log 工作过程

mysql 每执行一条 DML 语句,先将记录写入 redo log buffer,后续某个时间点再一次性将多个操作记录写到 redo log file。这种 先写日志,再写磁盘 的技术就是 MySQL 里经常说到的 WAL(Write-Ahead Logging) 技术。

在计算机操作系统中,用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernel space )缓冲区( OS Buffer )。

因此, redo log buffer 写入 redo logfile 实际上是先写入 OS Buffer ,然后再通过系统调用 fsync() 将其刷到 redo log file 中,过程如下:

支持三种将 redo log buffer 写入 redo log file 的时机,可以通过 innodb_flush_log_at_trx_commit 参数配置:

由 binlog 和 redo log 的区别可知:binlog 日志只用于归档,只依靠 binlog 是没有 crash-safe 能力的。

但只有 redo log 也不行,因为 redo log 是 InnoDB特有的,且日志上的记录落盘后会被覆盖掉。因此需要 binlog和 redo log二者同时记录,才能保证当数据库发生宕机重启时,数据不会丢失。

# 3. undo log

undo log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为undo log)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用undo log中的备份将数据恢复到事务开始之前的状态。

简单来说就是,比如你执行一条 INSERT 语句,就会对应一条DELETE 的 undo log ,所以发生错误或者回滚了,就能回滚到事务之前的状态了。

#

# 4. 场景假设

假设数据库里有一行数据: id = 1, name = '张三'

现在执行一条SQL语句:

UPDATE user SET name = '李四' WHERE id = 1;

# 1. Undo Log 记录了“改之前的样子”

  • 作用:为了能在你后悔时(回滚),把数据变回原来的样子。

  • 记录内容:它只关心这一行数据变更前的状态。它会记录:

    “这行数据(id=1)原来的名字是 ‘张三’。”

  • 记录时机:在修改数据之前,就先把这个“旧值”记下来。

流程比喻: 你在改作文之前,先把原文复印一份存起来。如果改坏了,拿出复印件就能恢复原状。


# 2. Binlog 记录了“怎么改的”

  • 作用:为了让别的数据库跟我保持一致(主从复制),或者以后查账(数据恢复)。

  • 记录内容:它关心的是执行了什么样的操作。根据格式不同,它可能记录两种形式:

    • 如果是 Statement 格式(逻辑SQL):

      “刚才执行了一条SQL:UPDATE user SET name = ‘李四’ WHERE id = 1;”

    • 如果是 Row 格式(行变更):

      “主键 id=1 的那一行,name 字段从 ‘张三’ 改成了 ‘李四’。”

  • 记录时机:事务提交时才记录。如果事务没成功,Binlog 里就没有这条记录。

流程比喻: 你把改好的作文交给老师(主库),老师先在草稿本上(Binlog)记下“某年某月某日,李华把作文改成了……”,然后再把这篇作文展示给全班同学(从库)看。

# 3. Redo Log — 记录“改之后的样子”(物理级别)

  • 目的:崩溃恢复时用,已提交的事务如果数据还没刷到磁盘,就用它来重做。
  • 内容:物理日志,记录“哪个数据页的哪个位置改成了什么值”。
  • 记录时机:修改数据的同时记录(WAL,Write-Ahead Logging,日志先行),事务提交时必须刷盘。

记录内容示例:

“第 5 号数据页(page 5),第 1024 字节处(偏移量),写入了字符串 ‘李四’。”

注意:它不关心你执行的是什么 SQL,只关心磁盘上的数据块哪里被改动了。


# 整个执行过程的对比

结合 Redo Log,这三个日志在一条 UPDATE 语句执行时的分工是这样的:

  1. 准备阶段(执行SQL):
    • Undo Log:先把 name = ‘张三’ 这个旧值记下来(以便将来回滚)。
    • 然后修改内存中的数据:把内存里的 name 改成 ‘李四’。
    • Redo Log:把这个修改动作(在哪个数据页、哪个位置写入了‘李四’)记下来(以便崩溃后恢复)。
  2. 提交阶段(Commit):
    • Redo Log:进入 Prepare 阶段(准备就绪)。
    • Binlog:把整个修改操作记录成文件(写入磁盘)。
    • Redo Log:进入 Commit 阶段(标记事务成功)。
    • 最终:内存中的数据,会在合适的时机刷到磁盘。

# 总结例子中的区别

针对刚才那条 UPDATE 语句,三个日志分别记了什么?

  • Undo Log(为了回滚):

    {id: 1, name: ‘张三’} (只记旧值)

  • Redo Log(为了崩溃恢复):

    {页号: 100, 偏移量: 50, 数据: ‘李四’} (只记新值的物理位置)

  • Binlog(为了复制/恢复):

    UPDATE user SET name = ‘李四’ WHERE id = 1; (记整个操作)

所以,虽然它们都在“记录”,但 Undo Log 是为了“撤销修改”,而 Binlog 是为了“重复执行”。

# 5. 总结

对比维度 undo log(回滚日志) redo log(重做日志) binlog(二进制日志)
日志层次 InnoDB 存储引擎层 InnoDB 存储引擎层 MySQL Server 层
主要作用 保证事务的原子性,用于事务回滚和 MVCC 保证事务的持久性,用于崩溃恢复 用于数据恢复和主从复制
记录内容 数据的逻辑变化,记录的是"修改前的数据"(前镜像),如执行 INSERT 时记录对应的 DELETE 信息 数据的物理变化,记录的是"哪个数据页的哪个位置修改成了什么值" SQL 语句的逻辑变化(或行变更),如执行一条 UPDATE 语句,记录对应的修改逻辑
记录时机 事务执行过程中,在修改数据之前生成 事务执行过程中不断写入,事务提交时必须写入磁盘 事务提交时,将事务中的所有修改一次性写入
文件数量 通常是单个或多个回滚段文件 固定数量的文件(循环写入,可配置) 多个文件(可追加,可滚动)
生命周期 事务结束后并不会立即删除,用于 MVCC 的历史版本读取,当没有事务需要访问旧版本数据时才会被清理 循环写入,旧日志会被覆盖 日志文件保留直到手动删除或达到过期时间

简单来说:

  • undo log:负责撤销,记录"改之前的样子"
  • redo log:负责重做,记录"改之后的样子"
  • binlog:负责备份和同步,记录"怎么改的"
阅读全文
×

(为防止恶意爬虫)
扫码或搜索:HelloCoder
发送:290992
即可永久解锁本站全部文章

解锁
#binlog#redolog#undolog#区别#作用#区别和作用
上次更新: 2026-03-13 10:04:40
最近更新
01
《LeetCode 101》
03-13
02
《LeetCode CookBook》
03-13
03
IDEA、Golang、Pycharm破解安装
03-13
更多文章>
Theme by Vdoing | Copyright © 2020-2026 码农阿雨
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式