MySQL InnoDB存储架构【2】——磁盘架构
前言
参考:MyQL官方文档
接上文 MySQL InnoDB存储架构【1】——内存架构
MySQL 版本 8.0.26
在 innoDB 存储引擎中,磁盘架构包含 表,索引,表空间,双写缓冲区,重做日志(redo log),撤销日志(undo logs)
1. 创建表时,表空间所在位置
从InnoDB的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace)
file-per-table tablespace
默认
innodb_file_per_table = 1
, 创建表时,会在 file-per-table tablespace——@@datadir/{database}/
下创建一个 {table_name}.idb 文件。system tablespace
如果
set global innodb_file_per_table = 0
,创建表时,就会在 system tablespace——@@datadir/ibdata1
中创建表空间,不会再创建数据和索引文件(对于MyISM 是分开的)file-per-table tablespace
且目录在特定目录innodb_file_per_table = 1 或者建表时 使用
tablespace file-per-table
子语句指定表空间, 并且使用DATA DIRECTORY
指定目录。
数据文件存储在指定目录
需要满足几个条件# 查看几个相关路径, datadir 是数据库数据存储路径, SELECT @@datadir,@@innodb_data_home_dir,@@innodb_directories; # 数据目录,必须在innodb_directories 中 # 如果没有需要在 mysql.conf 中 [mysqld] 做如下配置 ## 以分号“;”分隔 #innodb_directories="/opt/ext_data_dir/" CREATE TABLE t1 (c1 INT PRIMARY KEY) DATA DIRECTORY = '/opt/ext_data_dir/'; # CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE = innodb_file_per_table DATA DIRECTORY = '/opt/ext_data_dir/';
- 文件夹必须存在
- 文件夹路径,必须在变量 innodb_directories 中
- *ux 用户 mysql拥有 目录的权限
- innodb_file_per_table = 1 或者建表时 使用 tablespace 子语句 指定表空间
general tablespace
(通用表空间) // TODO
2. 表空间结构
参考 MySQL 8.0 Reference Manual 15.11.2 File Space Management
Extents, Segments 是逻辑上的定义。
page 是物理上概念,一个page代表一个连续的大小为 page size 的 物理空间
2.1 Page
每一个表空间都是由数据库 Page 组成的,对于一个数据库实例来说,Page 的大小都是一样的,默认是 16k。1
2.1 Extent
- 对于 page size <= 16k , Extent 大小为 1M,即一个64个连续的 16k page, 128个 8k page, 256个 4k page
- 对于 page size = 32k,Extent 大小为 2M,即一个 Extent 包含 64个 page
- 对于 page size = 64k,Extent 大小为 4M,即一个 Extent 包含 64个 page
2.2 Segment
如果将 tablespace 当成目录,则 Segments 是它的文件
When a segment grows inside the tablespace, InnoDB allocates the first 32 pages to it one at a time. After that, InnoDB starts to allocate whole extents to the segment. InnoDB can add up to 4 extents at a time to a large segment to ensure good sequentiality of data.
当一个segment在表空间内增长时,InnoDB第一次分配前 32 Page 给它。之后,InnoDB分配 整个 Extent 到 Segment。 InnoDB 一次最多可以将 4 个 Extent 添加到一个大的 Segment 中,以确保数据的良好顺序性。
- InnoDB 中的每个索引都分配了两个段。一种用于 B+ 树的非叶节点,另一种用于叶节点。
- 使叶节点在磁盘上保持连续可以实现更好的顺序 I/O 操作,因为这些叶节点包含实际的表数据。
- 对于聚簇索引来说,叶子节点保存了真实的记录
- 叶子节点的数据结构是有序双向链表
2.4 文件结构
ibd 文件结构2
- FSP HEADER PAGE
FSP HEADER PAGE 是表空间的root page,存储表空间关键元数据信息。由 page file header (文件信息)、fsp header(表空间元信息)、xdes entries(描述extent的xdes(extent descriptor)信息的链表) 三大部分构成 - IBUF BITMAP PAGE
用于跟踪随后的每个page的change buffer, 使用4个bit来描述每个page的change buffer信息。3 - INODE PAGE
表空间文件的第3个page的类型为FIL_PAGE_INODE,存储inode(index node),管理表空间的segment。每个inode对应一个segment。每个inode page默认存储FSP_SEG_INODES_PER_PAGE(85)个inode。每个索引使用2个segment,分别用于管理叶子节点和非叶子节点。 - 接下来的页,就是用来存储 索引 b+ 树的叶子节点和非叶子节点
我创建了一张最简单的表
create table t1(id int auto_increment primary key);
查看对应的表空间文件大小为 112k,也就是 7 页
- FSP HEADER PAGE
- IBUF BITMAP PAGE
- INODE PAGE
- 非叶子节点
- 叶子节点
- 预留page,新创建的表空间,且当前的文件小于1个Extent时,则只分配2个Page
通过 innblock 查看数据
root:/opt/project/innblock-master# ./innblock /var/lib/mysql/test/t2.ibd scan 16
Datafile Total Size:114688
===INDEX_ID:165
level0 total block is (1)
block_no: 4,level: 0|*|