一、InnoDB存储引擎主键
如果在创建表的时候没有显示的定义主键(primary key),则InnoDB存储引擎会按如下方式创建主键。
首判断表中是否有非空的唯一索引,如果有则该列即为主键
不符合上面条件,则InnoDB会默认自动创建一个指针(6个字节)
二、InnoDB逻辑存储结构
1、整体介绍
InnoDB所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace),也就是
.ibd
文件,所以其是有共享表空间以及每个表独立的表空间。
表空间又由段(segment)、区(extent)、页(page)组成,页在有些文档也被称为块(block)
2、表空间
表空间可以看为是InnoDB存储引擎逻辑结构的最高层,所有的数据都是存放在表空间中,同时可以通过
innodb_file_per_table
来让每个表都有自己独立的表空间。
每张表独立的表空间存放的只是数据、索引、插入缓冲,其他的例如Undo信息,系统事务信息、二层写缓冲等还是存放在原来的共享表空间中,即默认的
ibdata1
文件。
3、段
表空间是由各个段组成的,常见的段有数据段、索引段、回滚段。同时由于InnoDB存储引擎是索引组织的(index organized),则时间段即为B+树的页节点(上图的 leaf node segment),索引段即为B+树的非索引节点(non-leaf node segment)。
需要注意的是,并不是所有对象都有段,所以可以理解为表空间是由分散的页与段共同组成的。
4、区
区是由64个连续的页组成的,每个页是16KB,所以每个区是1MB。对于大的数据段,InnoDB存储引擎每次最多可以申请4个区,以此来保证数据的顺序性能。(连续的页,所以InnoDB在申请内存空间的时候,是按区申请的?)
5、页
页是InnoDB进行磁盘管理的最小单位。常见的页类型有:
数据页(B-true Node)
Undo页(Undo Log Page)
系统页(System Page)
事务数据页(Transaction system Page)
插入缓冲位图页(Insert Buffer Bitmap)
插入缓冲空闲列表页(Insert Buffer Free List)
未压缩的二进制大对象页(Uncompressed BLOG Page)
压缩的二进制大对象页(Compressed BLOG Page)
6、行
InnoDB是面向行的,也就是说数据的存放是按行进行存放的。书上写的是每个也存放的行是有规定的,最多是7992行记录。
三、InnoDB物理存储结构
1、整体介绍
从物理意义来看,InnoDB表是由共享表空间(
ibdata1
文件)、日志文件组也就是
Redo
文件组(默认的
ib_logfile0
、
ib_logfile1
文件)、表结构定义文件(
.frm
文件,这个是与mysql相关的,其他的引擎也有这个文件)。开启
innodb_file_pre_table
的话,就还有每个表的独立表空间(
.ibd
文件),其存储数据、索引、表的内部数据字典。
四、InnoDB行记录格式
记录在页中是保存表中一行行数据。可以通过
show create table xxx\G
来查看
可以看到这里的
Row_format
行格式是
Dynamic
(书上是以Compact格式为例,不过各种格式整体记录的核心信息应该大同小异的)
1、Compact行记录格式
1)、变长字段长度列表
其是用来表示变长字段的,当列的长度小于255未的时候用1字节表示,大于用两个字节表示,也就解释了
varchar
类型最大长度是65535(但实际是小于这个数的,因为还有别的默认的开销)。
2)、NULL标志位
该位表示此行数据是否有NULL值,用1表示。
3)、记录头信息
4)、列数据
这个就是用来存储实际每列具体的数据。这里需要注意的是NULL值是不该部分任何数据的,其只有NULL标识位表示。同时每行数据除了用户定义的列外,还有两个隐藏列,事务ID列与回滚指针列。并且如果没有对应规则的主键,每行会增加一个默认的RowId列。
然后书上还有介绍
Redundant
行记录格式,这个就不介绍了。
2、行溢出数据
InnoDB存储引擎可以将一条记录中的某些数据存储在真正的数据页面之外,即作为行溢出数据。一般的
BLOB
、
LOB
这种大对象列类型可能会发生。但其实其会看数据存储的数据大小,也可能不会发生,书上是以
varchar
这种类型举例,
varchar
类型也可能会行溢出数据。如果
sql_mode
设置为严格模式的话,可能会有警告,设置
varchar
大小为65535。这个
sql_mode
其实就是可以设置对列这些进行严格模式进行校验,可以去具体了解下。
五、InnoDB数据页结构
通过前面的介绍我们知道,页类型为
B-tree node
的页,其存放的就是表中行的实际数据。
1、数据页组成
2、File Header
File Header
是用来记录页的一些头信息,由8个部分组成:
1)、FIL_PAGE_SPACE_OR_CHECKSUM
表明该页属于哪个表空间,这是因为如果没有开启
innodb_file_per_table
,所有表信息都是放在
idbdata1
文件,所以就需要建立对应页的表空间。
2)、FIL_PAGE_OFFSET
表示表空间中页的偏移量
3)、FIL_PAGE_PREV、FIL_PAGE_NEXT
表示当前页的上页及下页
4)、FIL_PAGE_LSN
表示该页最后被修改的日志序列位置LSN(Log Sequence Number)。这个是用来校验页数据的,后面会有介绍
5)、FIL_PAGE_TYPE
表示页的类型,一般取值有:
6)、FIL_PAGE_FILE_FLUSH_LSN
该值仅是数据文件中的一个页中定义,代表文件至少被更新到了该LSN值
7)、FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID
该值表示页归属于哪个表空间。
3、Page Header
其是用来记录数据页的状态信息,由14个部分组成
1)、PAGE_N_DIR_SLOTS
在Page Directory(页目录)中的Slot(槽)数。Page Directory中存放了记录的相对位置
2)、PAGE_HEAP_TOP
堆中第一个记录的指针。
3)、PAGE_N_HEAP
堆中的记录数
4)、PAGE_FREE
指上空闲列表的首指针
5)、PAGE_GARBAGE
以删除记录的字节数。即行记录结构中,delete_flage为1的记录大小的总数
6)、PAGE_LAST_INSERT
最后插入记录的位置
7)、PAGE_DIRECTION
最后插入的方向
8)、PAGE_N_DIRECTION
一个方向连续插入记录的数量
9)、PAGE_N_RECS
该页中记录的数量
10)、PAGE_MAX_TRX_ID
修改当前页的最大事务ID,该值仅在Secondary Index定义
11)、PAGE_LEVEL
当前页再索引树中的位置。0x00表示节节点
12)、PAGE_INDEX_ID
当前页 属于哪个索引ID
13)、PAGE_BTR_SEG_LEAF
B+树的页节点中,文件段的首字节位置。该值仅在B+树的Root页中定义
14)、PAGE_BTR_SEG_TOP
B+树的非叶节点中,文件段的首指针位置。该值仅在B+树的Root页中定义。
4、Infimun与Supremun记录
每个数据页中有两个虚拟的行记录,用来限定记录的边界。
Infimun
记录比该页中任何主键都要小的值,
Supremun
是都要大
5、User Records与FreeSpace
User Records是实际存储行记录的内容。FreeSpace是空闲空间,是链表数据结构。当一条记录被删除后,该创建就会天骄到空闲链表中。
6、File Trailer
为了保证页能够被完整写入磁盘,InnoDB存储引擎的页中设置了
File Trailer
部分。该值只有
FIL_PAGE_END_LSN
部分,8字节。前4给字节表示该页的
checksum
值,后4个字节与前面
File Header
中的
FIL_PAGE_LSN
相同。通过这两个值的比较是否相同,来保证页的完整性。