Skip to Content
面试题库Mysql[面试题] 一次insert操作,MySQL的几种log的写入顺序?

[面试题] 一次insert操作,MySQL的几种log的写入顺序?

📖 版块 A:知识讲解版 (温故知新)

在 MySQL(InnoDB 存储引擎)中,一次 INSERT 操作涉及三种核心日志:Undo Log(回滚日志)Redo Log(重做日志)Binlog(归档日志)。它们的协同工作遵循 两阶段提交(2PC) 协议,以保证事务的 ACID 特性及主从一致性。

具体的写入逻辑步骤如下:

  1. Undo Log 写入:在修改数据前,先记录数据修改前的状态(对于 INSERT 则是记录主键 ID,回滚时执行 DELETE),用于事务回滚和 MVCC。
  2. 内存修改:在 Buffer Pool 中执行数据页的修改。
  3. Redo Log 写入 (Prepare 阶段):将物理修改记录到 Redo Log Buffer,并根据刷盘策略(innodb_flush_log_at_trx_commit)写入磁盘。此时事务处于 Prepare 状态。
  4. Binlog 写入:将逻辑操作记录到 Binlog Cache,并在事务提交时将缓存写入磁盘中的 Binlog 文件。
  5. Redo Log 写入 (Commit 阶段):在 Binlog 写入完成后,在 Redo Log 中记录一条 commit 标识,标记事务正式提交。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:一次 insert 操作,MySQL 的几种 log 的写入顺序?

💬 高手逐字稿

关于一次 INSERT 操作涉及的日志写入顺序,我们不能简单地看作是线性排列,它其实是一个交织的事务流程,核心是围绕着“两阶段提交”展开的。

首先,在真正执行插入动作之前,MySQL 会先记录 Undo Log。这是为了保证原子性,如果后续操作失败,系统可以根据 Undo Log 进行回滚。

接着,InnoDB 会修改内存中的数据页,并把这次修改记录到 Redo Log 中。但注意,这时候的 Redo Log 处于 prepare 阶段。之所以要先写 Redo Log,是因为它遵循 WAL(Write-Ahead Logging)原则,保证了即使此时宕机,数据也不会丢失。

随后,执行器会生成该操作的 Binlog,并将其写入磁盘。Binlog 是逻辑日志,主要用于主从复制和数据恢复。

最后,当 Binlog 写入完成后,InnoDB 会把刚才那条 Redo Log 的状态修改为 commit 状态。到这一步,整个事务才算真正提交完成。

【高手自问自答】这里其实涉及到一个经典的问题: 为什么非要搞个两阶段提交,而不直接先写 Redo 再写 Binlog?

这是为了防止主从数据不一致。假设我们先写完了 Redo Log 没写 Binlog 系统就崩了。重启后,主库能通过 Redo Log 恢复数据,但因为 Binlog 没记录,从库就不会同步这条数据,导致主从不一致。而采用了两阶段提交后,重启恢复时会检查:如果 Redo Log 处于 prepare 状态,MySQL 会去查看 Binlog 是否完整。如果 Binlog 已经写完了,就会自动提交 Redo Log;如果 Binlog 没写完,则会利用 Undo Log 回滚。这样就通过日志的顺序和状态,完美解决了分布式事务的一致性问题。

最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册