InnoDB redo、undo、binlog,是如何合作的

MySQL日志有重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)、错误日志(errorlog)、慢查询日志(slow query log)、一般查询日志(general log)、中继日志(relay log)。

这次主要讲redo log、undo log、binlog之间的联动。 很多细节不会讲解,只梳理最核心的流程。

1.简介

binlog:

  • MySQL的server层日志。

  • 用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步;

  • 用于数据库的基于时间点的还原;

redo log:

  • InnoDB存储引擎日志。

  • 确保事务的持久性。

  • 防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。

undo log:

扫描二维码关注公众号,回复: 13442180 查看本文章
  • InnoDB存储引擎日志。

  • 确保事务的原子性。

  • 提供回滚和多个行版本控制(MVCC)。

2.一条SQL更新语句执行流程

让我们通过一条语句看一下binlog、redo log、updo log是如何联动的。更新语句真正的执行流程要比下面列的复杂的多,只说核心流程,方便理解。《MySQL45讲》中对于这部分讲解缺乏一些细节,这里也做了补充。

2.1流程

  1. 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。

  2. 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。

  3. 引擎

  • 将这行新数据更新到内存中

  • 先将更新记录到undo log里,记录状态为prepare

  • 然后将这个更新操作记录到 redo log 里面,此时redo log 处于 prepare 状态

  • 然后告知执行器执行完成了,随时可以提交事务

  1. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘

  2. 执行器调用引擎的提交事务接口

  • 引擎将undo log改为完成状态

  • 引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

图中白色是在InnoDB存储引擎中完成的,深色框是在Server层的执行器完成的。

图片

这里要重点说一下xid:xid是一个唯一值,表示事务分支标识符。

当Innodb的参数innodb_support_xa打开时,在执行事务的第一条SQL时,就会去注册XA,根据第一条SQL的query id拼凑XID数据,然后存储在事务对象中。

redo log、undo log、binlog都包含xid,所以可以通过这个唯一值将三个日志串起来。

2.2二阶段提交

通过上面的流程图,可以发现事务处理使用的是二阶段提交方案。为什么要这么做呢?

redo log和binlog都能用于数据恢复,只不过使用时机不太一致。MySQL重启时会使用redo log,将还未落盘的数据落盘。binlog可以用于将主库或者从库恢复到指定时间。

如果redo log和binlog不一致,会导致数据不一致。如主库数据和从库数据不一致,问题就大了。而两阶段提交就能让这两个状态保持逻辑上的一致。

要完全搞明白二阶段提交为什么能够保持redo log和binlog的一致性,就需要了解MySQL启动时做了什么?

3.MySQL启动

当MySQL启动时,对于redo log中的记录有几种可能性:

  1. 记录已经为commit状态

  2. 记录为prepare状态,同时没有写binlog

  3. 记录为prepare状态,成功写入binlog

对于记录为commit状态,直接提交,将数据落盘即可。

对于记录为prepare状态,此时能够通过xid查看是否成功写入binlog

  • 如果没有写入binlog,通过undo log进行回滚

  • 如果写入binlog,则进行提交,实现数据落盘

通过MySQL启动时的规则配合二阶段提交,成功保证了binlog和redo log的一致性。其实也很容易发现,binlog一旦写入成功,事务最终必然会提交。

总结

MySQL知识挺多挺杂挺细,这次有很多内容没有讲,如buffer、LSN、checkpoint、三种日志的结构、MTR InnoDB 物理事务、undo对不同SQL处理方案不同等。网上的资料也一言难尽,如果大家有兴趣,可以看一下《MySQL运维内参》和源码,相信可以收获很多。当然,也可以看一下事务原子性、一致性、持久性的实现原理

资料

  1. MySQL到底有多少种日志类型需要我们记住的!

  2. MySQL · 引擎特性 · InnoDB 崩溃恢复过程

  3. MySQL事务提交过程

  4. MySQL 中Redo与Binlog顺序一致性问题 【转】

  5. MySQL · 引擎特性 · InnoDB undo log

  6. mysql事务执行顺序_MySQL innodb引擎的事务执行过程

  7. MySQL InnoDB Recovery过程解析

  8. MySQL运维内参

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

图片

往期文章回顾:

  1. 设计模式

  2. 招聘

  3. 思考

  4. 存储

  5. 算法系列

  6. 读书笔记

  7. 小工具

  8. 架构

  9. 网络

  10. Go语言

猜你喜欢

转载自blog.csdn.net/shida219/article/details/119520979
今日推荐