Posted by lily's blog on May 9, 2025

undo-log

作用

  1. 搜索引擎层用于事务回滚的日志,目的是用于保证事务的原子性
  2. MVCC的实现是通过:read view + undo log实现的。

实现过程

  1. 事务开始后,根据不同的增删改类型的语句在undo-log中记录不同的数据,以便于事务回滚后数据的恢复。并且在记录行上维护undo-log中两个额外的字段事务id和roll_point指针。数据行之间由roll_point指针连接,数据行被串成一条版本链。
    1. 增语句:记录新增语句的id,回滚只需要删除改行即可。
    2. 删除:记录被删除行的数据
    3. 修改:记录改行原本的数据内容
  2. 如果事务还未提交前数据库发生崩溃,那么就可以用undo-log回滚事务。
  3. 如果事务超时未提交,需要结束事务时也会利用undo-log进行回滚。

如何持久化的?

undo-log也是通过redo-log来进行持久化的。

被修改的数据写入缓冲池中,被修改的数据页被标记为脏页。脏页会被写入redo-log中,通过redo-log刷盘机制进行

在缓冲池中有undo页,修改undo-log也是通过把数据添加到undo页中,对undo页的修改也会记录到redo-log中,redo

redo-log

存储模型

如何刷盘

bin-log

存储模型

刷盘时机

undolog解决redolog不完整

参考文章:

  1. [两阶段提交](https://cloud.tencent.com/developer/article/2384265

InnoDB在因sql执行失败或者MySQL服务宕机导致redolog不完整从而出现数据不一致是这么解决的:

  1. 在更新数据页之前,InnoDB会先将数据当前的状态记录在「Undo Log」中。
  2. 之后,再将更新后的相关数据记录到「Redo Log」中。

undo log是以页为单位,跟随页的刷新机制,会存在丢失的情况,所以在记录undo后也会将该undo记录到redo,避免undo丢失,一旦undo丢失就回滚不了了。

有了undo log后,假设第二条sql执行失败,这个时候就会通过行记录中的事务ID(txidx)和回滚指针(roll_pointx、roll_pointx1)去undolog中找对应的回滚操作,最终将事务回滚保证原子性和一致性。

如果发生宕机,那么在重新MySQL服务时,会有两个操作:

  1. 会先通过redo log构建「脏页」。
  2. 根据redo log中记录的事务提交状态来决定是否回滚。

两阶段提交解决binlog和redolog的不一致

XA的两阶段分别是prepare和commit,在事务提交前,redolog中记录的状态都是prepare,当事务提交后,该状态就会被更新为commit,同时将XID写入到对应的binlog中并刷新到磁盘。

XA两阶段提交保证了binlog和redolog逻辑一致,从而避免主从节点的数据不一致。

总结

MySQL一致性的保证基本上涉及到InnoDB存储引擎的各个组件,「Buffer Pool」、「Log Buffer」、「Redo Log」、「Undo Log」等,还有DML操作的流程、锁、故障恢复等功能。最后再总结下MySQL是如何保证一致性的。

  1. 对于并发操作带来的数据不一致性问题,InnoDB通过锁来解决。
  2. 对于可能会发生的redolog不完整的情况,InnoDB通过Undo Log来解决。
  3. 对于redolog&binlog不一致带来的主从节点数据不一致,MySQL是通过XA两阶段提交来解决。