MySQL 三大日志:Redo、Undo 与 Binlog 详解

写在前面

关于三大日志,博主看了无数视频和文章,也是总结的非常精辟了!

在 MySQL 数据库的运行机制中,Redo Log、Undo Log 和 Binlog 起着至关重要的作用,它们各司其职,共同保障数据库的数据安全、事务一致性以及高效的复制与恢复功能。接下来,我们就深入探究这三大日志的区别、作用,以及在 SQL 更新操作中的协同工作过程,同时揭开两阶段提交的神秘面纱。

三大日志的区别与作用

①Redo Log:数据持久化

Redo Log 记录事务对数据库数据的修改操作,其核心目标是确保事务提交后数据的持久性。当执行UPDATE employee SET salary = 60000 WHERE id = 101;这样的语句时,Redo Log 会记录下对 employee 表中 id 为 101 的 salary 字段的修改操作。即使在事务提交后系统出现崩溃等异常情况,重启数据库时,Redo Log 也能根据记录将数据恢复到正确的状态,保证已提交事务的数据不会丢失 。

②Undo Log:事务回滚

Undo Log 记录的是数据的旧值,主要用于事务回滚。比如在执行上述更新语句前,salary 字段的旧值为 55000,Undo Log 会保存这个旧值。当事务需要回滚时,数据库就可以依据 Undo Log 中记录的旧值,将数据恢复到修改前的状态,以此保证事务的原子性和一致性 。

③Binlog:数据复制与恢复

Binlog 即二进制日志,记录了所有数据变更的 SQL 语句或事件,在 MySQL 中,它是实现主从复制和数据恢复的关键。以#Format Description Event 5.7.34-log 20:14:55 // QUERY_EVENT: UPDATE test.employee SET salary = 60000 WHERE id = 101;为例,Binlog 会记录下这条数据变更的 SQL 语句。通过解析 Binlog 中的内容,从库可以同步主库的数据变更,同时在数据出现丢失或损坏时,也能利用 Binlog 进行数据恢复 。

SQL 更新操作中三大日志的协同工作

当客户端向 MySQL 发送更新请求后,执行器会调用 InnoDB 存储引擎的 API 进行数据读写操作。InnoDB 通常利用 Buffer Pool 内存区域进行数据处理。

  1. 加锁与数据加载:首先,MySQL 依据执行计划,针对受影响的数据行加锁(在可重复读和读已提交隔离级别下,InnoDB 采用 Next-Key-Locking 行锁机制避免幻读),并将需要修改数据所在的一整页完整加载到 Buffer Pool 中。
  1. Undo Log 记录旧值:为了支持事务回滚,Undo Log 会记录下数据的旧值,为后续可能的回滚操作做好准备。
  1. 修改数据与 Redo Log 记录:接着,Buffer Pool 中的数据被修改,形成脏页。为防止系统故障导致数据丢失,新的修改值会被记录到 InnoDB 的 Redo Log Buffer 中。若采用innodb_flush_log_at_trx_commit = 1策略,数据写入 Redo Log Buffer 后,会立即写入 PageCache,再通过fsync()方法刷盘到 Redo Log,并将 Redo Log 中对应记录状态设为 prepare,完成事务提交第一阶段。
  1. Binlog 写入与两阶段提交:随后进行 Binlog 的写入操作,写入完成后,为确保 Binlog 和 Redo Log 的一致性,会将 Binlog 内容同步到 Redo Log,并把 Redo Log 中记录状态修改为 commit,完成两阶段提交。
  1. Buffer Pool 异步刷盘:最后,Buffer Pool 中的脏页会以异步方式进行刷盘操作。

两阶段提交:保障日志一致性的核心机制

两阶段提交的出现原因

在数据库事务处理中,特别是涉及到 Redo Log 和 Binlog 的交互时,若不采用特定机制,可能会出现两者数据不一致的情况。比如在事务提交过程中,若先写入 Redo Log,后写入 Binlog,在写入 Binlog 前系统崩溃,就会导致 Redo Log 和 Binlog 记录的事务状态不一致,影响数据恢复和主从复制。两阶段提交就是为了解决这类一致性问题而诞生的。

两阶段提交的流程

两阶段提交分为准备阶段(prepare)和提交阶段(commit)。在准备阶段,事务先将 Redo Log 记录状态设为 prepare,并记录相关修改;在提交阶段,写入 Binlog 后,再将 Redo Log 记录状态更新为 commit,以此确保 Redo Log 和 Binlog 记录的事务信息一致。

异常情况处理

若在准备阶段出现异常,如系统崩溃,由于事务未提交,重启后可依据 Redo Log 中 prepare 状态的记录和 Binlog 的情况,决定是回滚事务还是继续提交;若在提交阶段出现异常,因为 Binlog 已写入,数据恢复时可通过 Redo Log 和 Binlog 的配合,保证事务最终提交,确保数据一致性 。

MySQL 的 Redo Log、Undo Log 和 Binlog 在数据库运行中相辅相成,两阶段提交机制更是为数据一致性提供了坚实保障。深入理解它们的原理和工作过程,对优化数据库性能、保障数据安全具有重要意义。

博主总结(博主对自己只想点赞)

总结一下一条sql的执行流程

  • 当客户端发送请求到执行器后,接着执行器会调用存储引擎的 API (一般是innoDB)来进行数据的读写。innoDB通常会使用内存来进行操作,这个内存区域被称为BufferPool。
  • 首先根据执行计划,MySQL需要对受影响的数据行进行加锁(对于可重复读和读已提交隔离级别,InnoDB会使用Next---Key---Locking行锁机制来防止幻读),以确保事务的隔离性和一致性。接着会将要修改数据的一整页都完整加载到BufferPoll中。
  • 然后为了写入的数据支持回滚,所以通过UndoLog进行记录旧值。
  • 接着修改BufferPool上的数据,形成了脏页。为了防止由于系统故障导致的丢失数据,需要使用RedoLog。所以在这同时,也会将修改的新值记录到innoDB上的RedoLog Buffer上。
  • 在RedoLog Buffer上采用innodb_flush_log_at_trx_commit = 1(实时写,实时刷)的策略,一旦数据写入到RedoLog Buffer上后,紧接着就会将RedoLog Buffer上的数据写入到PageCache上,然后直接调用fsync()方法将数据刷盘写入RedoLog上。并将redolog上这行记录的状态修改为prepare,完成事务提交第一阶段。
  • 然后可以进行binlog的写入,写入完成后为了保证binLog和Redolog的一致,会将binlog内容同步到redolog上,并将redolog上这行记录的状态修改为commit,完成两阶段提交。
  • 最后可以异步地进行BufferPool的刷盘。
相关推荐
AA-代码批发V哥1 小时前
MySQL-多表查询深度解析与实战指南
mysql
Lx3523 小时前
EXPLAIN工具:查询执行计划分析与索引诊断
sql·mysql·性能优化
架构个驾驾3 小时前
Express 框架深度解析:从基础到实战的完整指南
javascript·mysql
kingbal3 小时前
MySQL:要删除子查询所涉及表中的数据,直接使用原 SQL 会报错
数据库·sql·mysql
独爱竹子的功夫熊猫4 小时前
数据库技巧:REPLACE INTO的高效替换方法
数据库·后端·mysql
cocosum5 小时前
树莓派5 安装Mysql (Docker + mariadb)方案
linux·数据库·mysql·docker·mariadb
学博成5 小时前
安装MySQL 5.7导入数据,修改密码,创建账号并授权
mysql
pan_junbiao5 小时前
MySQL中的SELECT FOR UPDATE的用法与原理
数据库·mysql
青衫码上行12 小时前
【MySQL数据库 | 第五篇】DDL操作2
数据库·mysql