美文网首页
二、MySQL 的redo log 和 binlog

二、MySQL 的redo log 和 binlog

作者: 从不中二的忧伤 | 来源:发表于2021-05-30 10:36 被阅读0次

    一条查询语句的执行过程,一般是经过 连接器、分析器、优化器、执行器,最后到达存储引擎。

    那么对于一条 更新的 MySQL 语句,执行流程又是怎样的呢? 首先可以肯定的是,以上查询语句经过的流程,更新语句也会走一遍。

    但是与查询流程不一样的是,更新流程还涉及到两个重要的日志模块: redo log(重做日志) 和 binlog(归档日志)。

    重做日志 redo log

    InnoDB 使用到的记录修改日志的技术是 WAL (Write-Ahead logging),其关键点就是先写日志,再写磁盘。
    当有一条记录需要更新时, InnDB 引擎会先把记录写入 redo log 中,并更新内存。然后,在适当的时候,将此操作记录更新到磁盘中。

    image.png

    如上所示,为 InnoDB 的 redo log 示意图。 redo log 的大小是固定的,会有两个指针记录关键的位置: write pos 是当前记录位置,checkpoint 是当前要擦除的位置,也就是把记录更新到磁盘。这两个指针都是不断向后推移并循环的。而 write pos 和 checkpoint 之间的位置就是可以用于记录新的操作的空间。

    有了 redo log, InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录不会丢失,并且可以根据 redo log 恢复,此能力称为 crash-safe。

    归档日志 bin log

    上面提到的 redo log 是 InnoDB 引擎特有的日志,而 Server 层也有自己特有的日志,称为 binlog。

    binlog 和 redo log 有以下几点不同:
    1、binlog 是 Server 层实现的, redo log 是 InnoDB 特有的。
    2、redo log 是物理日志,记录的是“在某个数据页上做了什么修改”,而 binlog 是逻辑日志,一般记录的是原修改 SQL 语句。
    3、redo log 是循环写的,空间有固定大小,并且可能会用完。binlog 是追加写入的,写到一定大小后可以切换下一个,并不会覆盖之前的日志。

    image.png

    以上是 update 语句的流程图,浅色框代表在 InnoDB 内部执行, 深色框是在执行器中执行。

    可以注意到,最后三个步骤,将 redo log 的写入拆成了两步骤: prepare 和 commit ,这就是 “两阶段提交”。

    两阶段提交

    “两阶段提交”的机制,是为了让两份日志之间的逻辑一致。

    可以考虑这么一个场景:当发生了误删表的操作,需要如何找回数据:
    1、找到最近一次的全量备份
    2、从这个备份时间点开始,将备份的 binlog 依次取出,重新放到误删表之前的那个时刻。
    3、然后此备份就和误删之前的线上库一样了。

    那么,到底为什么需要“两阶段提交”呢? 这里用 反证法举例说明,如果不用两阶段提交,会发生什么?

    假设有这么个字段 c=0,现在要将其修改为 c=1

    1、 先写 redo log 再写 binlog。如果写完 redo log ,还没来得及写 binlog 时,MySQL 异常重启。此时根据 redo log 恢复的 c=1,但是 binlog 还未写入,根据 binlog 恢复的临时库,c=0,与原库不一致。

    2、先写 binlog 再写 redo log。如果在写 redo log 之前,MySQL异常重启,那么此事务无效,c的值应该是0。但是根据 binlog 恢复的临时库,会多一次事务出来,导致与原库值不相同。

    相关文章

      网友评论

          本文标题:二、MySQL 的redo log 和 binlog

          本文链接:https://www.haomeiwen.com/subject/lbxrjltx.html