原创 MySQL不会丢失数据的秘密,就藏在它的 7种日志里

发布时间:2021-08-02 12:40:32 浏览 915 来源:猿笔记 作者:程序员内点事

    负责对SQL解释、分析、优化、执行操作引擎等,负责MySQL中数据的存储和提取。而MySQL中支持事务的存储引擎又属`InnoDB`使用的最为广泛!MySQL的数据是存放在磁盘中的。每次读写数据都需做磁盘IO操作,这个缓存中包含了磁盘中**部分**数据页(`page`)的映射,当向数据库写入数据时。此时缓存中的数据页数据变更,`BufferPool`中修改完数据后会按照设定的更新策略,此时`BufferPool`中修改的数据还没有及时的刷到磁盘中,它记录的是数据库中每个页的修改,可以用来恢复提交后的物理数据页,有了redolog再修改数据时:


    #主题列表:juejin,github,smartblue,cyanosis,channing-cyan,fancy,hydrogen,condensed-night-purple,greenwillow,v-green,vue-pro,healer-readable,mk-cute,jzman,geek-black,awesome-green,qklhk-chocolate

    #投稿主题:

    theme:juejin

    highlight:

    本文收录在GitHub地址

    在进入正题之前,先简单看一下MySQL的逻辑架构。我相信我能使用它。

    MySQL的逻辑架构大致可以分为三层:

    -第1层:处理客户端连接、授权和认证、安全检查等。

    -第二层:服务器` server '层,负责解释、分析、优化和执行SQL的操作引擎。

    -第三层:存储引擎,负责MySQL中的数据存储和提取。

    我们要知道MySQL的服务器层并不管理事务,事务是通过存储引擎实现的,而MySQL中支持事务的存储引擎使用最广泛的是` innodb ',所以后面文章中提到的存储引擎主要是` innodb '。

    * *记住!* * * *记住!* * * *记住!* *如上图所示,这是MySQL更新数据的基本流程,包括redolog '、binlog '和undolog '之间的一般关系,所以直接切入正题。

    ###redolog(重做日志)

    `redolog`属于MySQL存储引擎`InnoDB`的事务日志。

    MySQL数据存储在磁盘上,每次读写数据都需要磁盘IO操作,所以在并发场景下性能会很差。为此,MySQL提供了一种优化方法,并引入了缓存缓冲池。该缓存包含磁盘中* *部分* *数据页(` page `)的映射,以减轻数据库的磁盘压力。

    从数据库中读取数据时,先从缓存中读取,如果不在缓存中,则从磁盘中读取,放入缓存中;向数据库写入数据时,应该首先将其写入缓存。此时,缓存中的数据页发生变化,这称为* *脏页* *。在“缓冲池”中修改数据后,将根据设置的更新策略定期刷到磁盘上。这个过程叫做* *刷脏页* *。

    ####MySQL宕机

    如果脏页没有完成,MySQL可以因为某些原因停止并重启。此时,“缓冲池”中修改的数据没有及时刷到磁盘,会导致数据丢失,无法保证事务的持久性。

    为了解决这个问题,引入了‘重做日志’,重做日志顾名思义,重在重做!它记录数据库中每个页面的修改,而不是某一行或多行是如何修改的。可用于恢复已提交的物理数据页面,只能恢复到上次提交的位置。

    “重做日志”使用“wal”(预写日志)技术,该技术的核心是在修改记录之前写入日志,并确保在事务提交完成之前将日志放在磁盘上。

    当重做日志可用于修改数据时,InnoDB引擎将首先在重做日志中写入更新记录,在BufferPool '中修改数据,并在提交事务时调用fsync '将重做日志刷至磁盘。至于缓存中更新的数据文件何时刷新到磁盘,它们由后台线程异步处理。

    * *注* *:此时重做日志的交易状态为“准备”,尚未提交成功。在“binlog”日志写入磁盘之前,它不会被更改为提交,事务将被视为真正提交。

    这样,MySQL在刷脏页前意外关机也没关系,只要重启时分析重做日志中的更改记录并重放,就可以再次刷盘了。

    # # # #固定大小

    重做日志采用固定大小循环写入的格式。重做日志满的时候,从头开始循环写,形成一个环。

    那为什么要这样设计呢?

    因为重做日志记录了对数据页的修改,如果缓冲池中的数据页被刷到磁盘上,这些记录将无效,新日志将覆盖并擦除这些无效记录。

    上图中的`writepos`表示redolog当前记录的日志序列号`LSN`(logsequencenumber),写入还未刷盘,循环往后递增;`checkpoint`表示redolog中的修改记录已刷入磁盘后的LSN,循环往后递增,这个LSN之前的数据已经全落盘。

    `writepos`到`checkpoint`之间的部分是redolog空余的部分(绿色),用来记录新的日志;`checkpoint`到`writepos`之间是redolog已经记录的数据页修改数据,此时数据页还未刷回磁盘的部分。当`writepos`追上`checkpoint`时,会先推动`checkpoint`向前移动,空出位置(刷盘)再记录新的日志。

    * *注意* *:重做日志已满。在擦除之前,需要确保存储器中与这些要擦除的记录相对应的数据页已经被刷到磁盘上。在擦除旧记录为新空间腾出空间的期间,你不能再接收新的更新请求,这时MySQL的性能会下降。因此,在并发量较大的情况下,合理调整重做日志的文件大小非常重要。

    ####crash-safe

    因为redolog的存在使得`Innodb`引擎具有了`crash-safe`的能力,即MySQL宕机重启,系统会自动去检查redolog,将修改还未写入磁盘的数据从redolog恢复到MySQL中。

    MySQL启动时,不管上次是正常关机还是异常关机,总会恢复。将首先检查数据页中的“LSN”。如果这个LSN小于重做日志中的lsn,即“writepos”位置,这意味着数据页上未完成的操作被记录在“重做日志”中,然后数据同步将从最近的检查点开始。

    简单理解一下,比如重做日志的‘LSN’是500,数据页的‘LSN’是300,说明重启前有些数据没有完全刷到磁盘,所以系统会在重做日志中重放序列号为‘LSN’的记录,从300到500。

    ###undolog(回滚日志)

    `undolog`也是属于MySQL存储引擎InnoDB的事务日志。

    ` un

作者信息

程序员内点事 [等级:3] 公众号:程序员内点事
发布了 67 篇专栏 · 获得点赞 5059 · 获得阅读 332382

相关推荐 更多