Undo log读书总结

===================2021-12-17=================

undolog里保存的不是一行记录的值,而是某一种操作的反向操作,其实这个很好理解,一个update更新一行,反向操作就update回去就行了。如果保存一行的全部数据,显然冗余了。

 为了提高undolog的写入性能,每个事务都有属于自己的undolog页面链表

本文参考自:

  https://blog.csdn.net/bohu83/article/details/81568341

  https://zhuanlan.zhihu.com/p/155958401

  https://baijiahao.baidu.com/s?id=1654809273831660358&wfr=spider&for=pc

 

  1 回滚段和UNDO 段

    不同于redo log,redo log可以指定存储的文件名和存储位置。undo log的存储以段为管理单位,而且实际也存储在每一个表空间文件中,而不会独立存在。

    在Innodb中使用表空间,回滚段,页等多级概念结构实现undo功能

 

    

  

    

 

    0号回滚段被预留在ibdata中,1~32号的32个回滚段是临时表的回滚段,存储于ibtmpl文件,其余从33号开始的回滚段才是可配置的,因此InnoDB实际支出96*1024个普通事务同时在线。

    每个回滚段的头部维护着一个段头页,该页中划分了1024个槽位slot(TRX_RSEG_N_SLOTS),每个slot可以对应一个undo log对象,这也是为什么说一个回滚段支持1024个事务。

    

      

  • PAGE HEADER:这是INNODB中的通用的PAGE HEADER,占据38字节,这里不作仔细描述
  • TRX_RSEG_MAX_SIZE:回滚段最大的大小,一般情况下为无限大
  • TRX_RSEG_HISTORY_SIZE:TRX_RSEG_HISTORY链表大小,即链表上的节点数量
  • TRX_RSEG_HISTORY:history链表,history链表用途后面会在以后详述。链表上的每个节点是一个地址结构,占据6个字节,包括page_no和offset。通过history list将不再使用的undo log构建成为一个链表,方便以后回收
  • UNDO LOG SLOT:默认有1024项,每一项对应一个特定的UNDO LOG。

  总结:一个段下面有1024个PAGE,该PAGE就是mysql中的一般的page,16KB。一个事务分配一个段,但是并非一个段只能给一个事务。

UNDO PAGE 格式

UNDO LOG存储在UNDO PAGE中。UNDO LOG也存在两种类型:insert undo和update undo。其中insert undo记录insert语句中生成的undo log,而update undo则记录update/delete等语句中生成的undo log。每个undo page只存储一种类型的UNDO LOG。

每创建一个trx_undo_t对象时,会先分配一个UNDO SEGMENT,以后该事务上所有的undo log所需page均从该SEGMENT上分配。而只有这个UNDO SEGMENT 的第一个PAGE被称为HEADER PAGE。HEADER PAGE与普通PAGE不一样的地方在于:它上面除了可存储普通的UNDO LOG外,还有UNDO_SEG_HDR信息,包含如下字段:

  TRX_UNDO_STATE:标记事务状态,有TRX_UNDO_ACTIVE/TRX_UNDO_PREPARED等状态
  TRX_UNDO_LAST_LOG:最后一个undo日志的在undo page中的偏移,通过该字段可快速定位最新undo日志的位置
  TRX_UNDO_FSEG_HEADER:不确定,占据10个字节大小
  TRX_UNDO_PAGE_LIST:该trx_undo_t所有的PAGE构成的双向链表头部。占据16个字节。通过它就可以遍历该trx_undo_t的所有undo page,进而找到所有的undo log内容,设计得还是很巧妙的

普通UNDO PAGE包含了header和body两个大的部分,而header中又包含三个子部分,分别是COMMON PAGE

HEADER和UNDO_PAGE_HDR。其中COMMON PAGE HEADER占据38B,是INNODB中所有PAGE共享,这里暂时不做说明。UNDO_PAGE_HDR包含以下字段:

TRX_UNDO_PAGE_TYPE:该undo page记录的undo类型,占据2个字节,目前有TRX_UNDO_INSERT、TRX_UNDO_UPDATE两种类型
TRX_UNDO_PAGE_START:该undo page记录的数据起始位置,undo log从page内的该偏移处写入,就是指图中的Data Region的起始偏移
TRX_UNDO_PAGE_FREE:该undo page记录的数据起始位置,undo log从page内的该偏移处写入,就是指图中的Data Region的起始偏移
TRX_UNDO_PAGE_NODE:这里是前后向指针,用于串联一个trx_undo_t内的所有UNDO PAGE,每个指针大小为6B,总大小12B

UNDO PAGE HEADER占据的大小为18B。

trx_undo_t、header page、undo page三者组成的关系如下图所示:

  

 

  2 分配undo log流程

申请 Undo Log 的流程如下:

  • 首先尝试从回滚段上的 reuse list 获取 Undo Log

  • 假如从回滚段的 reuse list 申请失败则需要基于事务启动时分配的回滚段申请 Undo Log 空间(trx_undo_create()):

    • 首先获取回滚段 Header(trx_rsegf_get()).

    • 从回滚段 Header 获取空闲的 Slot (trx_rsegf_undo_find_free()), 每一个 Undo slot 申请一个File Segment. (Segment的结构见InnoDB的文件组织结构)

    • 初始化 Undo Log Segment 的 Header Page 并更新回滚段的TRX_RSEG_UNDO_SLOTS

    • 根据事务的DML类型TRX_UNDO_INSERTTRX_UNDO_UPDATE分别创建的trx_undo_t加入对应的list:

    首先要明白两个概念,回滚段和undo 段,英文是rollback segment 和 undo segment.

    innodb有128个rollback segment 每个rollback segment有1024个undo segment。每个undo segment就对应一个事务,并且唯一有一个HEADER PAGE,用于管理属于这个事务的undo page。

    而每个undo segment所包含的数据页是不一定的,可多可少。

 

  3 undo log格式

    insert undo log(insert,insert只对本身事务可见,对其他事务无影响)

    

 

  update undo log

  

  上面两幅图前38个字节是文件头,和普通的数据页的前38个字节意义是一样的都是文件头。

  注意下UNDO LOG中的灰色的undo log header,格式如下:

  

  主要的字段作用是:

  

  其中UNDO LOG HEADER包含如下字段:

  • TRX_UNDO_DEL_MASKS:暂时不清楚含义
  • TRX_UNDO_TRX_ID:产生该UNDO LOG的事务id
  • TRX_UNDO_LOG_START:UNDO LOG DATA所在偏移
  • TRX_UNDO_XID_EXISTS:UNDO LOG HEADER中是否包含XID信息,本例中演示的场景是不含XID信息的头部(字段值为FALSE),也是老版本的格式,新版本中在头部包含了XID,会在接下来分析
  • TRX_UNDO_NEXT_LOG:该UNDO PAGE中后一个UNDO LOG所在偏移
  • TRX_UNDO_PREV_LOG:该UNDO PAGE中前一个UNDO LOG所在偏移
  • RESERVED:预留了不少字段,暂时不明白其具体含义

   我们在具体看一下update log 和 insert log 的存储结构。左侧是insert 右侧是 update

    

 

posted on 2020-09-11 12:13  MaXianZhe  阅读(312)  评论(0编辑  收藏  举报

导航