• 直读Innodb datafile


    这两天有空翻了翻大神写的《innodb存储引擎》,手痒亲身实践。由于此书出版了有段时日,没有用其推荐的python工具,通过点滴推敲,略微发现其中冰山一角的奥秘。对于今后对于一些问题查证或数据迁移可能会有帮助。话不多说,开码。

    ·大结构

    innodb数据文件按照 :【segment,extent,page,row】层次来组合,中文解释就是【段、区、页、行】。
    搜狗截图_2014-09-06_14-48-08_副本
    4大元素之间的关系:
    Segment=N*[Extent];
    Extent=64*Pages;
    Page=16KB(Low-Level fs+Page Header+VarcharLength+Data);
    Low-Level fs=38 Bytes;
    Page-Header=78 Bytes;
    Page-Header=【Page Header+虚拟记录mum】
    Data=16*1024B-38B-78B-VcharLength

    ibd文件由段组成,段有extent可以按需扩展,truncate能回收空间,但delete只做清零处理。
    extent扩展inndo有自己的经验算法,这块代码还没找到,理论是1-4M,但实际有出现扩从512K突增到9M的情况。有64个PAGE组成。
    Page大小16K,也就是16384个字节。按16进制,UltraEdit下步长起点如下:0000-4000-8000-C000
    Page按代码由3部分组成,逻辑上PageHeader对infimum和supremum有拆分。也可以说是4部分组成。后面会讲。

    ·小结构

    段和区都为固定功能且可以单调递增,暂不做解释。主要讲一下Page和Row。Row走最常见的compact格式,compact本质取消了一定规则内存对齐操作。
    Page的构造如下:
    搜狗截图_2014-09-06_14-53-07
    这些结构体的文件系统底层定义在$MYSQL_SRC/storage/include/fil0fil.h中可以查到,主要这两个字段在分析中比较有用:

    • Offset :记录着Page的偏移,也就是我这页是第几个页。
    • Prev和Next:页的双向链表,实际存的不是指针,就是Offset的值。
    • Type:帮助你了解这个页是干什么的。0x45bf,代码中是17855十进制。该值为最典型的数据PAGE。
    • Space_id:这个表的ID,作为dict的唯一关联。
    • LSN:在备份和恢复时非常有用,有助于定位问题。

    再往下看,就是PageHeader。它的定义在$MYSQL_SRC/storage/include/page0page.h中可以查看
    搜狗截图_2014-09-06_14-53-18
    从0xc0205的0×0046 space_id开始算起,如上图所示,是所有page_header的定义和长度。这些定义主要是围绕了记录数的起始、大小、长度、位置等做的一些统计信息。
    注意图中的3条红色虚线,它们分别指出了具体记录的起点和结束位置。这个位置是相对ROW_ID为基础的。
    PAGE_HEAP_TOP:记录整个记录导出到buf堆时最后的指针停留位置,像上图中就是c000+00ec=c0ec。
    PAGE_LAST_INSERT:记录着这个PAGE中最后一条记录的起始位置,像上图中就是c000+00be=c0be。
    INFIMUM虚拟行记录头:记录着第一条记录的起始位置,像上图中就是c063+0023=c083。
    另外,PAGE_N_RECS:记录着这个页中包含着多少条记录等等。通过这样1头1尾定位了所有的记录框架。
    搜狗截图_2014-09-06_14-53-31
    上图就是与我们记录完全翻译的16进制解码,下图是原始记录。
    搜狗截图_2014-09-06_14-53-40
    对于Row的字段定义在$MYSQL/storage/rem/rem0rec.cc和row0row.cc中有明确解释。
    第一条记录全字段都被填满了,所以varchar_length预留了3个字节分别表示了t2,t3,t4存储的字符长度。
    空值判断预留了1位。这个比较有意思,该值是一个bitmap。这两段实现可以rem0rec.cc中查到。
    1个字节可以展示8个字段空与非空。2个字节就能支持到16个字段,以此类推。空了填1,不空填0,从右往左为视觉字段顺序。
    Row_ID:默认行记录key表示。再跟交易trx_ID和回滚指针。
    再往后就是varchar的变长真实数据和char的预留数据,char的预留数据为0×20空格,不是0。这个比较奇怪。
    图中红、黄、绿分别代表了3条不同的记录,与其自身下图select对应。

    至此,我们就可以对整个IBD文件进行了初步解析。

  • 相关阅读:
    window 编译lua 5.3
    邮件服务器软件
    mkyaffs2image 生成不了120M的镜像文件的解决方法
    C static struct
    uboot 如何向内核传递参数
    linux 链接理解
    snmp 协议之理解
    交叉编译知识点总结
    回滚原理 Since database connections are thread-local, this is thread-safe.
    REST 架构的替代方案 为什么说GraphQL是API的未来?
  • 原文地址:https://www.cnblogs.com/zacard-orc/p/3964155.html
Copyright © 2020-2023  润新知