MySQL_磁盘存储

MySQL磁盘存储

1.行格式

我们可以对一个表指定他的行存储的格式,这里我们用一个COMPACT格式,我们可以建表的时候指定,也可以后续修改

CREATE TABLE table_name (columns) ROW_FORMAT=COMPACT
ALTER TABLE table_name ROW_FORMAT=COMPACT

在这种格式下,每一行数据实际存储的格式大致如下:

变长字段的长度列表null值列表数据头column01的值column01的值column0n的值

对于每一行数据,他其实存储的时候都会有一些头字段对这行数据进行一定描述,然后再放上他这一行数据每一列的具体的值,这就是所谓的行格式,除了COMPACT以外,还有其他几种存储格式,基本都大同小异

2.变长字符串存储

比如有一行数据,VARCHAR(10),VARCHAR(5),VARCHAR(20),VARCHAR(1),VARCHAR(1),一共5个字段,其中三个是变长字段,假设一行数据是这样的:hello hi hao a a,现在三个变长的字段长度分别是0x05,0x02,0x03,但是实际放在变长字段长度列表的时候是逆序放的,所以一行数据实际存储可能是:
0x03 0x02 0x05 null值列表 头字段 hello hi hao a a

3.NULL值存储

对所有的NULL值不通过字符串在磁盘上存储,而是通过二进制的bit位来存储在NULL值列表里,假设一张表:

CREATE TABLE customer (

name VARCHAR(10) NOT NULL,

address VARCHAR(20),

gender CHAR(1),

job VARCHAR(30),

school VARCHAR(50)

) ROW_FORMAT=COMPACT;

现在有如下一行数据:

nameaddressgenderjobschool
jackmxx_school

首先变长字段的长度按照逆序放在变长字段长度列表中,NULL值在NULL值列表中体现出来,所有允许为NULL值的字段都有一个二进制bit位的值,1说明是NULL,0说明不是NULL,实际上NULL值列表也是逆序排放的,所以他的四个bit位是0101,NULL值列表存放的时候不会说仅仅是4个bit位,一般起码是8个bit位的倍数,高位补0,所以实际存放看起来如下:

0x090x0400000101头信息column01=value1column02=value2columnN=valueN

4.数据头的存储

数据头是用来描述这行数据的,有40个bit位,第一个bit位和第二个bit位都是预留位,没任何含义

  • delete_mask,1个bit位,他标识这行数据是否被删除
  • min_rec_mask,1个bit位,B+树里每一层的非叶子节点里的最小值都有这个标记
  • n_owned,4个bit位,记录了一个记录数
  • heap_no,13个bit位,他代表的是当前这行数据在记录堆里的位置
  • record_type,3个bit位,这就是说这行数据的类型,0代表普通类型,1代表B+树非叶子节点,2代表的是最小值数据,3代表的是最大值数据
  • next_record,16个bit位,这个是指向他下一条数据的指针

5.实际数据在磁盘上的存储

一行数据"jack NULL m NULL xx_school"真实存储大致如下所示:
0x09 0x04 00000101 0000000000000000000010000000000000011001 jack m xx_school
在读取这个数据的时候,它会根据变长字段的长度先读取出来jack,然后发现第二个字段是NULL,就不用读取了,第三个字段是定长字段,直接读取1个字符就可以了,第四个字段是NULL,就不用读取了,第五个字段是变长字段长度是9,读取出来xx_school就可以了
实际上字符串这些东西都是根据我们数据库指定的字符集编码,进行编码之后再存储的,大致看起来一行数据如下所示:

0x090x040000010100000000000000000000100000000000000110016161616363206262626262

在一行数据存储的时候,会在他真实数据的部分加入一些隐藏字段:

  • DB_ROW_ID字段,这就是一个行的唯一标识,是数据库内部搞得一个标识,不是主键ID字段,如果我们没有指定主键和unique key唯一索引的时候,内存自动加一个ROW_ID作为主键
  • DB_TRX_ID字段,这是跟事务相关的,事务ID
  • DB_ROLL_PTR字段,这是回滚针,是用来进行事务回滚的

加上这几个隐藏字段之后,实际一行数据可能看起来如下所示:

0x090x0400000101000000000000000000001000000000000001100100000000094C(DB_ROW_ID)00000000032D(DB_TRX_ID)EA000010078E(DB_ROL_PTR)6161616363206262626262

6.行溢出

行溢出就是说一行数据存储的内容太多了,一个数据页都存放不下,此时只能溢出这个数据页,把数据溢出存放到其他数据页里面去,那些数据页就叫做溢出页
比如有一个表的字段类型是VARCHAR(65532),这远大于16kb的大小了,实际上数据页存储这行数据,仅仅包含它一部分的数据,同时包含一个20个字节的指针,指向了其他的一些数据页,那些数据页用链表串联起来存放这个VARCHAR(65532)超大字段里的数据

7.数据页

数据页

8.表空间

表空间
我们平时创建的表,都有一个表空间的概念,在磁盘上对应着"表名.ibd"的磁盘数据文件,所以在物理层面上,表空间就是对应一些磁盘上的数据文件,有的表空间对应多个磁盘文件,有的表空间对应一个磁盘文件
表空间的磁盘文件里有很多数据页,一个表空间的数据页太多不便于管理,又引入数据区(extent)的概念,一个数据区对应着连续64个数据页,每个数据页是16kb,所以一个数据区是1mb,然后256个数据区被划分为一组
表空间的第一组数据区的第一个数据区的前三个数据页都是固定的,存放了一些描述性的信息:

  • FSP_HDR:存放了表空间和这一组数据区的一些属性
  • IBUF_BITMAP:存放着一组数据页所有的insert buffer信息
  • INODE:存放着一些特殊的信息

当我们执行CRUD操作的时候,就是从磁盘上的表空间数据文件里,去加载一些数据页到buffer pool的缓存页中去使用,我们插入一条数据,这个时候会看往那个表插数据,根据表找到对应的表空间,定位到对应的磁盘文件,有了磁盘文件就找一个extent区,再找一个数据页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值