MySQL中的数据是如何存储的

每次将数据刷盘都是将一个数据页刷入,而不是一行数据

存储格式如下

  • 变长字段的长度:16进制,如果有多个变长字段,它们的字段长度是逆序存储的,如果变长字段是NULL,则不需要存储其字段长度)
  • null值字段列表:存储bit位,比如该字段的值为NULL,则bit位的值为0,同变长字段的长度一样,也是逆序存储的
  • 数据头:40个bit
    • 第1、2个bit:预留bit,暂无作用
    • (1)delete_mask:标识行是否被删除
    • (1)min_rec_mask:B+树中每一层的非叶子节点中的最小值
    • (4)n_owned:记录数
    • (13)heap_no:该行数据在记录堆中的位置
    • (3)record_type:数据类型,0表示普通类型,1表示是B+树的非叶子节点,2表示是最小值数据,3表示最大值数据
    • (16)next_record:下一条数据的指针
  • 隐藏字段
    • DB_ROW_ID:行的唯一标识
    • DB_TRX_ID:事务ID
    • DB_ROLL_PTR:回滚指针,执行事务回滚时用到
  • 每个字段的值(编码后)

例:

CREATE TABLE `student`(
    name    VARCHAR(10) NOT NULL,
    address VARCHAR(20),
    gender  CHAR(1),
    job     VARCHAR(30),
    school  VARCHAR(50)
) ROW_FORMAT=COMPACT

同时有一行数据Jack NULL m NULL xx_school,其存储在磁盘上的形式为

0x09 0x04 00000101 40bit头信息 (DB_ROW_ID) (DB_TRX_ID) (DB_ROLL_PTR) Jack编码后的值 m编码后的值 xx_school编码后的值

MySQL中的数据页是如何存储的

数据页是MySQL中的最小操作单位,当我们修改数据时,都需要将数据所在的数据页从磁盘读入到Buffer Pool中,然后在Buffer Pool中对其进行操作,操作完成之后再将其刷回到磁盘

每个数据页的默认大小为16KB,其结构为

  • 文件头(38b)
  • 数据页头(56b)
  • 最小记录和最大记录(26b)
  • 多个数据行(不固定)
  • 空闲区域(不固定)
  • 数据页目录(不固定)
  • 文件结尾(8b)

初始状态下,即一个数据页中没有任何数据行时,数据行区域是不存在的

当插入一行数据时,会将该数据页加载到Buffer Pool中,然后从空闲区域中拿出一部分空间分配给数据行区域,当空闲区域耗尽时,表示该数据页已经满了

MySQL表空间概念

表空间其实就是一个磁盘文件,它们通常以表名.idb的格式存储,数据页都是放在表空间里的,但是因为数据页太多,所以,MySQL又引入了数据区(extent)的概念

所以表空间的基本结构如下

  • 一个表空间对应着一些磁盘文件
  • 每个表空间中有多组数据区,每组数据区中有256个数据区,一个数据区的大小为1mb
  • 每个数据区中存放着64个数据页
  • 每个表空间的第一组数据区的前三个数据页分别为FSP_HDR数据页(存放表空间和该组数据区的基本属性)、IBUF_BITMAP数据页(存放这组数据页中所有的insert_buffer信息)、INODE数据页
  • 其他每组数据区的第一个数据区的前两个数据页都是存放一些特殊信息