这篇文章是自己学习mysql随手写的杂记,编辑混乱且不够严谨,请勿参考,谢谢!
mysql innodb引擎将数据存储在磁盘中,不同的引擎存储形式不同,有的则不需要存储,比如memory引擎。
innodb引擎底层数据的存储格式形式如下:
变长字段长度列表 | NULL值列表 | 头信息 | 列1值 | 列2值 | 列n值....... |
前面三个单元格是记录的附加信息,为了标识和管理记录而添加的。头信息后面的是记录的真实数据部分,不过有三个隐藏的属性,db_row_id,db_transaction_id,db_roll_pointer分别是记录唯一标识,事务id,回滚指针等等。
如果建表时有主键或unique键,则采用其作为db_row_id,否则系统会生成一个来唯一标识一条记录。
db_transaction_id和db_roll_pointer在事务中会使用到。
变长字段如varchar,text等都属于此类字段,如果有col1,col2,col3变长字段,则会在变长字段长度列表栏位逆序存放真实数据所占字节数,需要注意的是:如果该列值为NULL,则变长字段长度列表是不会存该NULL值所占字节长度的。如果该列所允许存储的最大字节长度为255且真实数据所占字节超过127个字节则采用2个字节存储变长字段所占字节数,否则采用1个字节数来存储。对于CAHR(M)类型的列,虽然是定长列,但是如果编码字符集是变长字符集比如utf8(采用1-3个变长字节编码),则该列数据所占字节数还是会被加入到变长字段长度列表中的。NULL值列表只存储允许为NULL的列的NULL值情况,如果没有允许为NULL的列,则该NULL值列表则不存在。其中,存储时:1为NULL,0为非NULL。注意该部分需要整数个字节来表示,不足部分高位补0。头信息比较复杂,如下所示:
mysql规定:除BLOB和Text列除外,其他列存储的数据(不包括隐藏列和记录头信息)最大不能超过65535个字节。
一个VARCHAR(M)列存储的数据所占空间包括:
- 真实数据
- 真实数据占用字节的长度
-
NULL
值标识,如果该列有NOT NULL
属性则可以没有这部分存储空间
对于VARCAHR(M),如果采用的是ASCII字符集(1个字符使用一个字节表示,是定长字符集),且允许为NULL(去除1个字节),真实数据占用字节数去除2个字节。那么实际真实数据所占最大字节数为65535-2-1=65532,则M为65532/1,如果是gbk字符集,则为65532/2,utf8字符集为65532/3。
鉴于CPU和磁盘之间无法跨越的速度鸿沟,mysql读取记录时,按页为单位,写入时,也是以页为单位。一个页的大小为16kb,但是前面的所述一个列所允许存储的最大字节数为65535字节,那么很可能一个列存储的数据单个页无法装载,此时会把记录的部分数据放到其他页中存储,这称为"行溢出"。
对于compact行格式而言,列真实数据的前768个字节用于存储数据的一部分,后面的20字节用于指向存储剩余数据的页地址。
dynamic类型的行格式与其不同的是:列真实数据处不存储数据的前768个字节,而是把全部数据放到其他页中存储,此处只存的是指向其他页的地址。
compressed页会对数据压缩,节省存储空间。
完。