Mysql-物理存储

表, 字段, 行与表空间, 数据页的区别

我们操作的表, 字段, 行是逻辑概念, 实际存储在磁盘上的是表空间, 数据区, 数据页的物理概念.

一行数据的磁盘存储

磁盘中存储的数据长什么样子

变长字段的长度列表(16进制) null值列表 数据头 c1 c2 c3…

变长字段是如何存储的

变长字段如varchar(10), 值可能是hello, 也可能是hi, 长度是不确定的, 而多行数据实际上是紧密挨到一起存储的, 比如有两行数据, hello a a和hi a a, 其中a是char(1)定长字段, 在磁盘文件中存储的就是hello a a hi a a, 这样读取第一行数据就不知道怎么读取, 因为存在变长字段. 所以就用到了变长字段的长度列表: 如0x05 null值列表 数据头 hello a a 0x02 null值列表 数据头 hi a a
这样就可以知道变长字段的长度了. 比如有一个5列的数据有VARCHAR(10) VARCHAR(5) VARCHAR(20) CHAR(1) CHAR(1), 实际数据为hello hi hao a a, 最终效果如下:
0x03 0x02 0x05 null值列表 数据头 hello hi hao a a, 这里变长字段的长度列表和实际数据是反序的, 正常应该是0x05 0x02 0x03.

null值存储

对于值为null的字段, 并不能以字符串’null’的方式存储, 这不是在浪费空间嘛, 本来就什么值都没有. 实际上是以bit来存储的, 对于所有的允许为空的字段, 值为空用1表示, 值不为空用0表示.
而变长字段长度列表中存储的是不为null的字段长度列表, 而且null值列表bit位也是反序存储的,
如: varchar(10) not null varchar(5) char(1) varchar(3) varchar(15), 实际值为hello null a hi null, 实际是这么存储的: 0x02 0x05 00000110 数据头 hello …

40个bit的数据头

每一行数据除了都会有变长字段的长度列表, 逆序存放这行数据变长字段的长度, 还有一个null值列表, 对于允许为空的字段都会有一个bit标识那个字段是否为NULL, 也是逆序排列的, 还有一个40bit的数据头, 用来描述这行数据.
这40个bit位里,第一个bit位和第二个bit位,都是预留位,是没任何含义的。
然后接下来有一个bit位是delete_mask,他标识的是这行数据是否被删除了,其实看到这个bit位,这么说在MySQL里删除一行数据的时候,未必是立马把他从磁盘上清理掉,而是给他在数据头里搞1个bit标记他已经被删了
每一行数据都有一些数据头,不同的数据头都是用来描述这行数据的一些状态和附加信息的。
然后下一个bit位是min_rec_mask,他其实就是说在B+树里每一层的非叶子节点里的最小值都有这个标记。
接下来有4个bit位是n_owned,他其实就是记录了一个记录数,这个记录数的作用。
接着有13个bit位是heap_no,他代表的是当前这行数据在记录堆里的位置。
然后是3个bit位的record_type,这就是说这行数据的类型0代表的是普通类型,1代表的是B+树非叶子节点,2代表的是最小值数据,3代表的是最大值数据。
最后是16个bit的next_record,这个是指向他下一条数据的指针。

真实数据在磁盘中是怎么存储的

有一行数据是“jack NULL m NULL xx_school”,那么他真实存储大致如下所示:
0x09 0x04 00000101 0000000000000000000010000000000000011001 jack m xx_school

字符串显然不是直接存在磁盘上的. 要先进行字符集编码.
0x09 0x04 00000101 0000000000000000000010000000000000011001 616161 636320 6262626262
但是真实数据中还会隐藏一些字段, 如DB_ROW_ID作为每行数据的唯一标识.如果我
们没有指定主键和unique key唯一索引的时候,他就内部自动加一个ROW_ID作为主键。
接着是一个DB_TRX_ID字段,这是跟事务相关的,他是说这是哪个事务更新的数据,这是事务ID.
最后是DB_ROLL_PTR字段,这是回滚指针,是用来进行事务回滚的.
所以如果你加上这几个隐藏字段之后,实际一行数据可能看起来如下所示:
0x09 0x04 00000101 0000000000000000000010000000000000011001 00000000094C(DB_ROW_ID)
00000000032D(DB_TRX_ID) EA000010078E(DB_ROL_PTR) 616161 636320 6262626262

什么是行溢出?

磁盘中, 每行数据都是存在数据页中的, 每个数据页默认是16kb, 如果一行数据超过了16kb了呢?
其实数据中会有一个指针数据, 指向下一个数据页, 用多个数据页来存储这个数据.

数据页的磁盘存储

在这里插入图片描述
数据行实际存储在数据行区域, 直到空闲区域被占满.

表空间和数据区

一个表空间一般对应一个表的文件, 里面有很多数据页.
但是现在有一个问题,就是一个表空间里包含的数据页实在是太多了,不便于管理,所以在表空间里又引入了一个数据区的概念,英文就是extent.
我们平时创建的那些表都是有对应的表空间的,每个表空间就是对应了磁盘上的数据文件,在表空间里有很多组数据区,一组数据区是256个数据区,每个数据区包含了64个数据页,是1mb.
在这里插入图片描述

mysql数据页的随机读写及日志文件的顺序读写

随机对鞋可以通过IOPS指标和延迟来观察读写性能
顺序读写一般通过吞吐量指标衡量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值