• 聊聊 mysql 事务?(三:从redo log恢复数据)


            上篇文章提到,MySQL为了数据持久性,引入了redo log。那么在系统奔溃后,到底如何做数据恢复的呢?我们现在已经知道MySQL会定期做checkpoint,也就是更新checkpoint_lsn的值,可以理解为redo日志中,当前最大可以被覆盖的lsn值。

            某一时刻下,各重要lsn值对应如下,lsn代表当前已经写入的redo日志量(buffer),flushed_to_disk_lsn代表已经刷盘的日志量,checkpoint_lsn代表当前允许被覆盖的日志量。即得到如下关系:

    checkpoint\_lsn \leqslant flushed\_to\_disk\_lsn \leqslant lsn

            现在回到系统奔溃后如何恢复。

            首先就是要找到恢复的起点,checkpoint_lsn之前的redo日志对应的数据页都已经被刷到磁盘上了,那么自然这部分的数据不需要重新恢复了,所以起点是checkpoint_lsn。

            然后就是要找到恢复的终点,我们知道,redo log是以块为单位的,一个block512字节,而且是顺序写入,每个block中的log block header记录了该块的管理信息,其中一个字段LOG_BLOCL_HDR_DATA_LEN属性记录了当前block中使用了多少字节空间,如果这个属性小于512,那么说明后面没有日志了,这个block就是终点。

            最后,redo日志如何恢复数据的呢?redo日志有大大小小几十种类型,需要从物理、逻辑层面上展开来说。

            物理上,绝大多数日志类型都有种通用结构:

    • type:日志类型
    • spaceID:表空间ID
    • page number:页号
    • data:这条redo日志具体内容 

             通过物理结构,我们能够定位到数据发生变化的具体位置了。但是实际上数据恢复没有这么简单,除了修改具体内容以外,可能还要修改 PAGE HEADER , PAGE DIRECTORY等等地方的信息,反正就是:一次数据修改,需要更改的地方非常多。

            因此,从逻辑层面上说,MySQL并不是简单找到数据位置,然后修改;而是针对每种不同的log类型,调用不同的函数。函数里面封装了一系列操作,通过调用这些函数,才可以将页面恢复成系统奔溃前的样子(不仅包括恢复具体数据,还要恢复管理信息,以及其他关联信息等)。

    最后总结(持久性)

            MySQL的事务有四大特性,其中之一是持久性,这要求系统奔溃后数据可以被正常恢复。为了保证持久性,引入了redo日志。从性能方面考虑,redo日志先写到buffer区,在适当时机再刷盘到file。从存储方面考虑,为了防止log日志越来越大,MySQL采用了循环写入。为了保证循环写入时,不丢失未持久化的数据,又引入了checkponit的概念,通过checkpoint_lsn可以知道那些日志可以被覆盖。系统奔溃后,又可以通过checkpoint_lsn找到需要被重做的日志起点,以及根据页管理信息找到终点,最后根据每条日志类型不同,调用相关函数恢复数据到系统奔溃前的状态。

     

  • 相关阅读:
    Flutter Widget 如何启用和屏蔽点击事件
    vue3组件通信使用
    个人设计web前端大作业 HTML期末大作业 学生个人网页设计作品 学生个人网页设计作品 学生个人网页模板 简单个人主页成品
    SpringBoot利用jpa连接MySQL数据库
    python基于django的读书笔记共享平台
    设计模式之组合模式
    Scala面向对象部分演示(IDEA开发)
    【深度学习】attention机制
    【云原生之K8s】 Pod控制器
    java毕业生设计二手车交易市场网站计算机源码+系统+mysql+调试部署+lw
  • 原文地址:https://blog.csdn.net/weixin_40647516/article/details/126948034