一、mysql的4种行数据存储格式
mysql有4种存储格式:1)Compact 2) Redundant (5.0版本以前用,已废弃) 3) Dynamic (mysql5.7默认格式) 4) Compressed。 这是compact行格式数据存储结构:
DB_ROW_ID(row_id) 如果表中没有显式定义主键列,mysql会默认生成一个row_id作为隐式主键,且row_id是全局概念,每一次有一行新数据insert,都会获取Max Row ID再加1就形成了一个新的row_id
DB_TRX_ID 事务有关,跟回滚指针有关,6个字节
DB_ROLL_PTR 事务有关,跟回滚指针有关, 7个字节
delete mask : 标记为是否被delete语句commit,也就是mysql不会真正物理删除一行记录,在页面上重新组装一个新链表,称为垃圾链表,如果垃圾链表占用空间可重用的话就会重用。
二、溢出页
mysql规定每一页(可存放16384字节)必须至少存放 2 条数据,每一行除了存储真实数据之外,还会存储行的额外信息(比如索引信息),大概132个字节,另外:变长字段长度列表、NULL值列表、记录头信息、 这一堆还要花27个字节,也就是 132 + 2 * ( 27 + n) < 16384,所以这样会造成溢出页。另外,mysql对于一个varchar列最多可以定义为65535个字节大小,但是当一个列比如是varchar(40000),会超出mysql对于一页的磁盘存储大小16KB * 1024 = 16384 > 40000 个字节,这个就需要分页了,因为单页数据溢出了,这里也会产生了溢出页。
1)Compact和Redundant对于溢出的处理:mysql会存储768个真实数据的字节,并且用20个字节存储把其他数据存放到哪些页中去。
2)Dynamic和Compressed对于溢出的处理:干脆连768个字节也不存了,直接存储溢出页地址。
三、索引页格式
上面提到的132个字节,存的大概就是这些信息:
File Header : 文件头。存储双向链表信息,undo日志也,溢出页,索引页等等,标志该页是什么页。用4个字节存储当前页号,一页可以存储2的32次方文件,大约20多亿,一个innodb表空间可以存放20亿左右的页面 * 16KB = 64TB数据。mysql又用区去存储页,一区可以存储64页,大概是1M。于是mysql又用组来存储区,一个区是256组。总结:一个表空间有多个组,每个组有256个区,一个区有64页。
Page Header : 页头
Infimum + Supremum :两条虚拟记录,Infimum指向页里单链表的最小记录,经过所有真实数据行的指向串联之后,最后指向Supremum页里单链表的最大记录。所以B+tree里每个叶子节点都有一前一后两个虚拟记录,分别会被上一页指向和指向下一页。列表的查找,平均查找记录为n/2。为了提高效率,mysql把这一串列表分成几组,把每组的最大值存到Page Directory页目录里面,称之为 slot 槽。分槽是可以解决mysql顺序查找的弊端,slot的分组规定,最后一个slot记录数是1-8条之间,其他slot槽是4-8条之间。
User Records : 用户真实数据
Free Space :空闲空间
Page Directory : 页目录
File Trailer : 文件尾部,校验文件是否完整的信息。总共8个字节,前4个字节与File Header一模一样,然后有一个字节是校验盒,表示写入了完整的16KB一页数据,最后3个字节是“LSN”。
end.