咱们知道mysql插入语句后,都是存放在磁盘文件的,若是是多条数据的话,也是紧凑的挨在一块儿,好比下图:
可是实际上又有点不同,由于咱们建表的时候,有些字段的长度是可变的,好比咱们定义了varcher(10),可能就存了a,虽然能够经过补齐长度来实现每条数据的长度是同样的,但这样就浪费了存储空间,因此多条数据多是这样存放的:
若是数据长度不同的话,那mysql读取某一行的数据的时候,就很麻烦了,他不知道从哪里开始从哪里结束,因此每一条数据就包括两个部分的内容,一个是描述这条数据的信息,一个是实际的数据。
描述数据有三个部分,分别是变长字段的长度列表、null值列表、数据头。实际数据就是每一个字段的值紧凑的挨在一块儿。因此实际上每行数据的结构是这样的:mysql
咱们建立表的时候,就会指定字段的类型,好比column1是可变字段的,这个时候变长字段的长度列表会记录column1的长度,好比他的值是abc,那长度就是3,转十六进制的话就是0x03,他的存储是这样的:
咱们读取数据的时候,就能够经过0x03知道column1要取多少数据。
若是column2也是可变字段,好比他的值是de,那他的存储是这样:
这里须要注意的是,他的顺序跟字段的顺序是相反的。sql
变长字段是用来知道咱们每一个字段实际的占用长度,那null值字段其实就是代表哪些值是null的。由于某个字段是null的话,他实际上并不会存磁盘的,避免空间的占用。是否为空就两种状态,是或则不是,因此这里有二进制来表示,1表示null,0表示非null。每个容许null的字段对应一位,位数是8的倍数,不够就补零,因此咱们三个字段也是0000 0000。跟变长字段的长度列表同样,他也是逆序的,即第一个字段在最后一位,因此咱们假设第一行的column3是null,那null值列表就是001,逆序就是100,补齐0就是0000 0100,那存储是这样的:
经过变长字段的长度列表咱们知道字段应该读取的长度,经过null值列表咱们知道哪些字段应该忽略读的。编码
数据头有40位,后16位是next_record,他主要是记录下一行的数据指针。spa
咱们存到磁盘的时候,会经过必定的字符集编码进行对数据进行编码,而后存放。
除了咱们定义的表字段外,他还有其余的隐藏字段,好比DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR。
DB_ROW_ID是一行的惟一标识,若是没有指定主键,那他的值就是主键。
DB_TRX_ID用于存放事务的ID。
DB_ROLL_PTR用于事务回滚。
因此实际的存储以下(编码这里就略了):指针