InnoDB,是MySQL的数据库引擎之一,现为MySQL的默认存储引擎,为MySQL AB发布binary的标准之一。
InnoDB存储结构
-
以页为单位来管理存储空间;
-
以页作为磁盘和内存交互的基本单位;
-
默认页大小为16kb(所以最少一次从磁盘读取16kb的内容),可以通过innodb_page_size 修改页的大小(在初始化时指定 mysqld --initialize);
-
不同的行格式在磁盘上的存放形式也不同;
-
mysql规定一页中最少存储2行数据
-
页中需要占用的额外空间需要132字节
compact 行格式(其他的差不多)
-
变长字段长度列表(2字节)
-
变长字段包含 varchar varbinary text blob等
-
按真实占用的字节数逆序存放
-
长度列表只是表示当前字段在此占用的直接长度(方便探知和检索)
-
null值列表(1字节)
-
标记允许为NULL的列
-
用位来存储,1表示为NULL,0表示非NULL
-
null值列表必须是整数个字节(一个字节可以表示8列,设计表是,如果非null,一定要加上not null,字段多时,可以减少一些空间占用)
-
记录头信息
-
由固定的5字节组成
-
可以理解为记录的元数据
-
记录的真实数据
-
默认添加row_id(6字节,唯一标记)、trx_id(6字节,事务id)、roll_pointer(7字节,回滚指针)
-
数据过长时,只会存储前768字节的数据,超过的数据会存储到溢出页中(需要20字节指向真正存储的数据页);
综上:mysql一条记录最少额外占用最少27字节;
上面数据过长,是多长?假设,我们有1个列数据过长,我们可以通过 132+2(n+27)<16*1024 算出当n>8099的时候绝对会溢出;
主键生成策略:
-
优先使用自定义的主键
-
没有自定义主键选不允许为NULL的唯一业务主键
-
以上都没有使用mysql的row_id
InnoDB数据页结构
InnoDB有不同类型的数据页
-
存放表空间的页
-
存放数据的页
-
存放索引的页
-
存放inode信息的页
-
存放redo信息的页
-
存放undo信息的页
Page Header
存储在数据页中的状态信息,包含了存储了多少数据,还有多少空闲,最后插入记录的位置,当前页的最大事务id,在B+树中所处的层级,索引ID(B+树中)
File Header
标注了页号、上一个页的页号,下一个页的页号,页面最后修改对应的额LSN,页的类型,页面被刷新到了哪个LSN,属于哪个表空间
File Trailer
我们都知道磁盘的写入数据远不如内存的cpu缓存的写入。mysql通过redo log来保证最终写入的一致性。在mysql写入磁盘的时候
-
先将File Header 中的校验值写入到磁盘中
-
页面刷新到磁盘后,再将File Trailer中的校验写入到磁盘
-
前后一致写入成功
File Trailer中也会存储最后修改的LSN,如果不一致,会通过redo log进行修复。