一、行
1.1、类似VARCHAR这种变长字段,在磁盘上是如何存储的?
咱们在建表的时候都会规定一个字段的长度,包括varchar,比如varchar(255),那么这个字段在磁盘上就会占用255的长度吗?
显然不会,,如果是char类型,数据库是这样,但varchar采用了另一个方法,因为这个字段可能并不会每一行都会占满255,势必会造成很大的浪费。
所以数据库对varchar的处理是,在一行数据的头部用十六进制标识出这个变长字段的实际长度。
注意:如果一行有多个变长字段,标识长度的数据存放时是倒序存放,比如:0x03 0x05 aaaaa aaa
1.2、一行多个null值,如何存放?
如果这个字段是null,会不会存个null的字符串?
显然,又不会。
在长度标识和真实数据中间还有一个null值列表
这个null值列表存储的就是允许为null的字段的bit位,这句话也不准确。
是这样,比如一个表有4个字段,实际内容是 :0001 age null name 。 后三个字段可以为null,那么null值列表就有三个bit位,每一位代表一个字段,如果这个字段是null,bit位的值就是1,如果不是null,就是0.所以null值列表的数据是010
但,也是逆序存放,所以还是010
但,一般是8个bit位的倍数,所以是00000010
1.3、比较重要的头部信息
在null值列表和真实数据中间还有一个头部信息,长度为40个bit位,先说下第3位,其他先不说。第3位叫delete_mask,它标识这行数据是不是被删除了,所以说一行数据被删除不会立马在磁盘中删除。
所以整一行是这样的:
1.4、真实数据的隐藏信息
在真实数据前还设有三个隐藏字段,分别代表着唯一标识、事务相关、回滚指针,目前了解就好。
1.5、一行的大小超过了整整一个数据页怎么办?
一个数据页16KB,一行数据太多肯定会超过这个数据页的大小,这时候就会有一个 20个字节的指针,指向其他数据页,然后用链表连起来。
这叫行溢出。
二、页
2.1、数据页包含的内容
注意:在开始的时候是没有多个数据行的,到最后是没有空闲区域的。
三、表空间和数据区
3.1、表空间的概念
我们建的每一个表,在磁盘上都有一个表名.ibd的文件,比如:
所以,表空间就对应这些数据文件。
每一个表空间里包含很多的数据页,为了便于管理,引入了数据区的概念,每一个数据区包含连续的64个数据页,然后256个数据区划分为一个组。
此外,表空间的第一组数据区的第一个数据区的前三个数据页都是固定的,放了一些描述性的数据,此外,其他各组数据区,每一组数据区的第一个数据区的前两个数据页也都是存放特殊信息的。
四、数据读写机制
4.1、磁盘随机读与磁盘顺序写
读取的时候,你要读的数据页可能在磁盘的任意一个位置,方式是随机读,它的性能很差。衡量性能的有两个指标:IOPS和响应延迟
IOPS是每秒可以执行多少次磁盘读写操作,响应延迟就是随机读写的响应延迟。这两主要看存储介质,固态肯定要比硬盘好。
前边有讲过redo log日志,它就是顺序写,在一个磁盘日志文件的末尾追加日志。
五、物理硬件
5.1、RAID存储架构
了解就好。
最普通的,一台机器有一个硬盘, 在分区,然后把MySQL安装到某一个分区里。
稍微大一点的,搞磁盘阵列,就是说有很多磁盘,那肯定需要什么东西来管理。这个东西就是RAID。通过它我们知道写到哪块磁盘上,也知道去哪个磁盘取数据,此外,通过它还可以搞备份,一批数据写在多个磁盘上。
如果读过阿里巴巴OceanBase数据库的介绍,你肯定很熟悉。
本文同步分享在 博客“w_boyang”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。