innodb 大字段及blob page相关内容

简介

大字段表示varchar、blob、text等使用大空间的字段,下面先简单介绍大字段在行中的存储方式,然后再介绍数据页格式与溢出页格式了解其具体存储格式。由于大部分都是通过文档了解,代码看的不多,可能理解有错误的地方,欢迎提出。
(下文中图都是来自各文章)

行存储格式

mysql行存储格式

mysql上层(sql层)使用的行格式可用如下图表示,转载自MySQL Row Format(MySQL行格式详解)

mysql row

innodb 行记录格式

innodb有多种行记录格式,有Compact、Redundant(Antelope文件格式)和Compressed、Dynamic(Barracuda文件格式),下面主要对compact和Dynamic(mysql5.7 default)与大字段相关的部分进行一些介绍。详情可参考[1][2]

Compact

Compact格式对于大字段处理如图:
blob compact

由于innodb的表是按索引(B+树)来组织的,节点中放的是页(page),每个页至少需要存放两条数据,不然就成了链表了。当一个页中只能存放下一条数据时,就会放在溢出页中。

总之当字段长超过一个阈值就会把一部分存放在溢出页(Uncompressed BLOB Page)。

/** Determine if a record is so big that it needs to be stored externally.
@param[in]  rec_size    length of the record in bytes
@param[in]  comp        nonzero=compact format
@param[in]  n_fields    number of fields in the record; ignored if
tablespace is not compressed
@param[in]  page_size   page size
@return FALSE if the entire record can be stored locally on the page */
UNIV_INLINE
ibool
page_zip_rec_needs_ext(
    ulint           rec_size,
    ulint           comp,
    ulint           n_fields,
    const page_size_t&  page_size)
{
    ....
    return(rec_size >= page_get_free_space_of_empty(comp) / 2);
}

当需要放在溢出页时,它会把前 768 byte 放在row中,其余字节放在溢出页。

Dynamic

InnoDB also encodes fixed-length fields greater than or equal to 768 bytes in length as variable-length fields. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.
Whether any columns are stored off-page depends on the page size and the total size of the row. When the row is too long, InnoDB chooses the longest columns for off-page storage until the clustered index record fits on the B-tree page. TEXT and BLOB columns that are less than or equal to 40 bytes are always stored in-line.

Dynamic 对溢出数据的处理可看下图
dynamic off Page

Dynamic 在数据需要放在溢出页时把数据全部放在溢出页。

Note

  1. 如上英文所述,innodb对于char等也有可能放在溢出页处理。详情可参考[3]
  2. Compact和Dynamic 都用20byte指针表明溢出数据地址。其结构如下:4 byte space id;4 byte page id;4 byte blob header 在 page 中的 offset;8 byte 存在溢出页中的长度。

数据页格式

详情可参考[4][5][6]

innodb 数据页大致分为3部分:page header、page body、page tailer。下面主要讲一下page body。不同类型的page其主要区别在于body结构不同。

page space

page body

page body 主要用来存放实际record,主要可分为3部分(实际还有header等其他空间):user records、free records、free space。

  • user records 为已经分配在实际使用的record。
  • free records 为使用后删除的records,没有还给free space。其通过链表进行组织。新删除的放在链表头。
  • free space 为尚未分配的空间

在插入一行时,先在free records链表中查找是否有可用的record,若有直接使用,若无再在free space中分配。

删除时,把删除的record放入free records链表。

从上述方式可知,若数据长度不定,必然会产生不能使用的极小碎片,因此需要进行page重组。

page 重组

page 重组有page内调整(去除碎片)和page合并。下面只对page内调整进行简单介绍。详情可参考[7] [8]

页内调整

页内调整大致流程如下:

  1. 创建一个与page相同的tmp_page;
  2. 初始化page,把tmp_page中的record一行行拷到page。
  3. 删除tmp_page

外部存储页

溢出页

外部存储页有多种,这里主要讲一下Uncompressed BLOB Page,其格式如上图所示。其body部分主要分成两部份:header和data。header记录数据长度、下一个page的位置等;data即实际数据。

对于此page,每一行每个溢出字段都会对于一个page,不共享,其data部分只属于某一行的某一字段。无需重组。

参考资料

  1. InnoDB的行记录格式, Compact, Redundant, Compressed, Dynamic
  2. https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html
  3. InnoDB的行溢出数据,Char的行结构存储
  4. mysql中InnoDB引擎中页的概念
  5. MySQL系列:innodb源码分析之page结构解析
  6. INNODB 数据页结构
  7. DML对innodb page空间的影响
  8. innodb page重组空间压缩函数(btr_page_reorganize_low)注释
  9. MySQL · 引擎特性 · InnoDB 文件系统之文件物理结构
  10. MySQL 如何存储长度较大的varchar与blob
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

紫无之紫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值