zoukankan      html  css  js  c++  java
  • undo日志

    undo日志

    作用

    因一些原因(机器宕机/操作系统错误/用户主动rollback等)导致事务执行到一半,但这时事务的执行已经让很多信息修改了(提交前就会边执行边修改记录),但还有部分未执行,为了保证事务的一致性与原子性,要么全都执行成功,要么全都失败,所以就需要回滚,而rollback需要旧值依据,而这些旧值记录就存储在undo日志中。

    redo日志记录

    记录时机

    InnoDB存储引擎在实际的进行增删改操作时,每操作一条记录都会先把对应的undo日志记录下来。

    undo日志通用结构

    undo日志存储在类型为FIL_PAGE_UNDO_LOGO的页面中,而每条记录添加到数据页中时,都会隐式的生成两个列trix_id和roll_pointer,trix_id就是事务id,roll_pointer是指向记录对应的undo日志的一个指针

    • end of record:本条undo日志在页中结束地址
    • undo type:undo日志类型
    • undo no:undo日志编号,事务没提交时,每生成一条undo日志就递增1
    • table id:本条undo 日志对应记录所在table id(information_schema库中表innodb_sys_tables查看)
    • 主键各列信息列表:<len, value>关键列占用空间和真实值信息列表
    • start of record:本条undo 日志在页中开始的地址

    各操作所对应的undo日志结构不同

    1. INSERT:回滚时,就是删除掉新增的这条记录。暂时只考虑聚簇索引插入情况,因为二级索引也包含主键,所以删除时也会根据主键信息把二级索引中的内容也删除

      名称内容
      undo type TRX_UNDO_INSERT_REC
    2. DELETE:记录被删除时,该记录头部信息的delete_mask会置为1,且会根据头部信息中的next_record属性组成一个垃圾链表,而这个链表中各记录占用的空间可以被重用,数据页PAGE HEADER中有个PAGE_FREE属性记录了这个链表的头节点。这时我们需要将头部信息delete_mask置为1的记录从正常记录列表中删除,会经历两个阶段

      阶段一:该记录头部信息的delete_mask会置为1(处于中间状态,还在正常链表中,不在垃圾链表中),这是要回滚的。

      阶段二:在删除语句所在的事务提交后执行,使用专门的线程把记录从正常链表中移除,加入到垃圾链表的头节点处,调整数据页的一些信息和垃圾链表头指针,页中可用字节数量,页目录信息等。(todo 涉及到被删除记录空间重用过程)

      名称内容
      undo type TRX_UNDO_DEL_MARK_REC
      old trix_id delete mark前记录
      old roll_pointer 找到修改之前最近的undo日志,比如新增的日志
      index_col_info len 索引各列信息占用空间包括主键索引
      索引各列信息<pos,len,value> 被索引的各列的位置/占用空间/值
    3. UPDATE

      • 更新主键

        InnoDB需要对聚簇索引进行处理

        • 将旧记录delete mark,因为其他事务可能需要访问(事务隔离机制)
        名称内容
        undo type TRX_UNDO_DEL_MARK_REC
        • 重新定位,并新增一条记录插到聚簇索引中
        名称内容
        undo type TRX_UNDO_INSERT_REC

        这里会有两条undo记录

      • 不更新主键

        • 被更新各列占用存储空间都不变:直接在原纪录基础上改
        • .......变:用户线程同步地先从聚簇索引中真实的删除旧记录,不是delete mark,并修改一系列信息,再插入新记录
        名称内容
        undo type TRX_UNDO_UPD_EXIST_REC
        old trix_id  
        old roll_pointer  
        n_updated 被更新列的数量
        <pos,old len,old value> 被更新列更新前信息
        index_col_info len 索引各列信息占用空间包括主键索引
        索引各列信息<pos,len,value> 被索引的各列的位置/占用空间/值

    undo页面管理

    存储undo日志的页面类型为FIL_PAGE_UNDO_LOG,和其他类型的页相比,多了Undo Page Header/Undo Log Segment Header/Undo Log Header属性。

    通常InnoDB使用链表来管理页面信息,所以InnoDB会根据一个事务产生的所有undo日志存放页面的Undo Page Header--TRX_UNDO_PAGE_NODE而形成的链表,链表由ListBaseNode(存储头尾节点信息和节点数量)和ListNode(各页面基本信息和前后节点偏移量)组成

    链表类型
    • 普通表的insert类型为insert undo链表
    • 普通表的update类型为updat undo链表;
    • 临时表的insert类型为insert undo链表
    • 临时表的update类型为updat undo链表;

    一个事务可能有2*2个链表(为了提高并发场景下多事务写入undo日志的性能),这些链表的分配是按需分配的;每个事务的同类型链表不会存储到一起。

    对于还没有被重用的undo页面链表来说,undo页面链表的第一个页面称为first undo page,在生成时就被填充Undo Page Header/Undo Log Segment Header/Undo Log Header属性;其余页面称为normal undo page,在生成时只被填充Undo Log Header属性;填充之后才开始写入undo日志

    1. Undo Page Header
    • TRX_UNDO_PAGE_TYPE:undo日志类型,只有两大类,不同类型undo日志不存在一起,因为insert类型的undo日志在事务提交后可以直接被删掉,但是delete等日志还需要为其他事务服务

      • TRX_UNDO_INSERT:1:新增记录/更新记录主键语句产生
      • TRX_UNDO_UPDATE:2:一般由delete和update语句产生,如TRX_UNDO_DEL_MARK_REC
    • TRX_UNDO_PAGE_START:第一条undo日志在页面中的偏移量

    • TRX_UNDO_PAGE_FREE:页面中存储的最后一条undo日志结束时的偏移量

    • TRX_UNDO_PAGE_NODE:一个页面就是一个链表节点

    first undo page多了一个Undo Log Segment Header属性,它包含了该链表对应段的segment header信息及其他一些关于这个段的信息

    1. Undo Log Segment Header
    • TRX_UNDO_STATE
    • TRX_UNDO_LAST_LOG
    • TRX_UNDO_FSEG_HEADER
    • TRX_UNDO_PAGE_LIST
    1. Undo Log Header:

      存储这个undo日志的事务的属性信息

    undo页面重用

    在某个事务提交后,重用该事务的undo页面链表,

    但这个链表只能包含一个undo页面,这个undo页面的已使用空间小于整个空间的3/4,因为如果这个链表中有很多页面,接下来重用的事务的页面却没有这么多,意味着InnoDB还是得维护这么多页面,即使很多页面并没有被用到;

    在基于上述的要求下,insert undo日志链表可以直接被覆盖;

    但是update undo日志链表在事务提交后不能马上被删除,MVCC,所以想要重用这个undo链表只能在之前的undo页面后继续写入。

    undo页面链表管理

    InnoDB设计Rollback Segment Header页面来存储各个undo页面链表的frist undo page的页号(undo slot固定数量),以维护undo日志页链表,这样就可以通过这个undo slot找到和它有关的normal undo page;在还未向任何事务分配任何链表时,这些slot都处于FIL_FULL状态,被一个链表的first undo page申请后,就不是FIL_FULL状态了,下一个申请的链表判断后,跳到下一个slot中;如果已经没有slot可以分配,那就会报错,只能等待有事务提交让出位置。

    Rollback Segment Header页面对应着一个segment,称为Rollback Segment回滚段(只存储一个页面)

    Rollback Segment Header结构

    • TRX_RSEG_MAX_SIZE:它管理的undo日志页链表可存储的最大数量undo页面
    • TRX_RSEG_HISTORY_SIZE
    • TRX_RSEG_HISTORY
    • TRX_RSEG_FSEG_HEADER:这个回滚段的Segment Header结构
    • TRX_RSEG_UNDO_SLOTS:它管理的所有链表的first undo page的页号集合1024个slot(4*1024字节)

    todo 为事务分配Undo页面链表详细过程。

    精华都在后半段 涉及到系统表空间

  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/hangzhi/p/11427539.html
Copyright © 2011-2022 走看看