MySQL InnoDB inno_space 工具介绍

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: **什么是inno_space?**[inno_space ](./https://github.com/baotiao/inno_space) 是一个可以直接访问InnoDB 内部文件的命令行工具, 可以打印出文件的内部结构.Jeremy Cole 用ruby 写了一个类似的工具, 不过不支持MySQL 8.0, 并且ruby 编译以及改动起来特别麻烦, 所以用cpp 重写了一个.

什么是inno_space?

inno_space 是一个可以直接访问InnoDB 内部文件的命令行工具, 可以打印出文件的内部结构.

Jeremy Cole 用ruby 写了一个类似的工具, 不过不支持MySQL 8.0, 并且ruby 编译以及改动起来特别麻烦, 所以用cpp 重写了一个. inno_space 做到不依赖任何外部文件, 只需要make, 就可以得到可执行文件, 做到开箱即用.

inno_space 除了支持打印出文件的具体结构之外, 同时还支持修复 corrupt page 功能, 如果遇到InnoDB 表文件中的page 损坏, 实例无法启动的情况, 如果损坏的只是leaf page, inno_space 可以将corrupt page 跳过, 从而保证实例能够启动, 并且将绝大部分的数据找回.

inno_space 还提供分析表文件中的数据情况, 是否有过多的free page, 从而给用户建议是否需要执行 optimize table 等等

具体可以看代码, 在github 上面开源: https://github.com/baotiao/inno_space/commits/main

接下来会4篇文章介绍InnoDB 主要的从文件, page, index, record 在具体文件里面是如何分布的, 这里大量引用了Jeremy Cole 里面的图片和文章的内容.

同时介绍的过程会结合inno_space 工具直观的打印出文件的内部结构.

InnoDB 最后的数据都会落到文件中.

整体而言InnoDB 里面除了redo log 以外都使用统一的结构进行管理, 包括system tablespace(ibdata1), user tablespace(用户表空间), undo log, temp tablespace. 这个结构我们统称space file.

  1. InnoDB space file 也就是整个InnoDB 文件系统的管理, 介绍.ibd 文件的基础结构. InnoDB space file
  2. InnoDB page management 具体的在InnoDB file space 这些16kb 大小的page 是如何管理的 Page management
  3. InnoDB Index page 上面讲了这16kb 的page 如何管理, 那么我们细看一下最常见的page 类型, Index Page 存的是用户表空间的数据, 这些Index Page 是如何维护成一个table 的数据 Index page
  4. InnoDB record 是具体在InnoDB page 里面, Mysql 里面的record 是如何保存在InnoDB page 里面的 InnoDB record

这篇文章只描述InnoDB file space, 接下来会有文章介绍InnoDB page management, InnoDB page, InnoDB record

1. InnoDB space file 基本结构

Page

在InnoDB 里面, 16kb 大小的page 是最小的原子单元

其他的大小都是在page 之上, 因此有:

1 page = 16kB = 16384 bytes

1 extent = 64 pages = 1 MB

FSP_HDR page = 256 extents = 16384 pages = 256 MB

page 有最基础的38字节的 FIL Header, 8字节的FIL Trailer

主要的内容包括:

  1. Checksum: 这个page 的checksum, 用来判断page 是否有corrupt
  2. Page Number: Page Number 可以计算出在文件上的偏移量, 一个page 是否初始化了, 也可以看这个page number 是否设置对了, 这个值其实是冗余的, 根据file offset 可以算出来, 所以这个值是否正确, 就可以知道这个page 是否被初始化了
  3. Previous Page/Next Page: 这个只有在Index page 的时候才有用, 而且只有leaf page 的时候才有用, non-leaf page 是没用的, 大部分类型的page 并没有使用这个字段.
  4. LSN for last page modification: 刷脏的时候, 写入这个page 的 newest_modification_lsn

    ​ mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn);

  5. Page Type: 这个page 具体的类型, 比如是btree index leaf-page, undo log page, btree index non-leaf page, insert buffer, fresh allocated page, 属于ibdata1 的system page 等等. Page Type 最重要, 决定这个page 的用途类型, 里面很多字段就不一样了
  6. Flush LSN: 保存的是已经flush 到磁盘的page 的最大lsn 信息. 只有在space 0 page 0 这个page 里面有用, 其他地方都没用.. 什么用途?什么时候写入? 什么时候读取?

    在进行shutdown 的时候, 或者执行force checkpoint的时候通过 fil_write_flushed_lsn_to_data_files 写入.

    用途是在启动的时候, 读取这个flush lsn, 可以确保这个lsn 之前的page 已经刷到磁盘了, 从这个flush lsn 之后的redo log 才是uncheckpoint redo log, 但是其实redo log 里面已经有了 checkpoint 的信息了, 为何还需要这个字段?

    logs_empty_and_mark_files_at_shutdown =>

    在实例启动的时候, innobase_start_or_create_for_mysql => open_or_create_data_files => fil_read_first_page

    fil_read_first_page 里面会读取出这个lsn 信息, 用于更新启动的时候的 min_flushed_lsn, max_flushed_lsn. 因为这个时候redo log 模块还没有初始化, 可以拿这个两个Lsn 做一些简单的判断

    整体来看, 这个字段目前已经没啥用了, 但是每一个page 都占用了8字节的空间, 还是比较浪费, 可以充分复用

  7. Space ID: 当前Page 所属space ID (8.0 里面已经将该字段删除了)

通过inno_space 可以看到相应的结构:

./inno -f ~/git/primary/dbs2250/sbtest/sbtest1.ibd -p 10

==========================block==========================
FIL Header:
CheckSum: 2065869235
Page number: 10
Previous Page: 9
Next Page: 11
Page LSN: 554513658770
Page Type: 17855
Flush LSN: 0

Space file

一个space file 就是2^32 个page 的合集, 连续64个page 叫做extent, 256个连续的extent 会有一个XDES(extent descriptor) 进行管理, 第一个XDES 又叫做FSP_HDR, 还有一些额外的信息.

下图就是这个基本文件组织结构的描述, 无论是undo space, system space, 用户的table space 都是这样结构

所有的space file 前3个page 都是一样.

page 0 是 FSP_HDR(file space header)

page 1 是 insert buffer bitmap

page 2 是 inode page, 下一节会介绍

The system space

system space 的space id = 0, 文件名叫 ibdata1, 也就是系统文件.

page 0, 1, 2 这3个page 所有的space file 都一样

在system space 里面接下来的3, 4, 5 等等page 也都是有指定的用途

page 3 存放的是insert buffer 相关信息

page 4 存放的是insert buffer tree 的root page

page 5 存放的是trx_sys 模块相关信息, 比如最新的trx id, binlog 信息等等.

page 6 存放的是FSP_FIRST_RSEG_PAGE_NO, 也就是undo log rollback segment的header page. 其他的undo log rollback segment 都在不同的undo log 文件中

page 7 存放的是 FSP_DICT_HDR_PAGE_NO, 存放的是DD 相关的信息

page 64-127 是first 64 个double write buffer 的位置

page 128-191 是second 64个double write buffer 的位置

剩下的其他page 就有可能被申请成Undo log page 等等了

通过inno_space 打开 ibdata1文件可以观察到如下的信息

File path /home/zongzhi.czz/git/primary/log2250/ibdata1 path
File size 209715200
start           end             count           type
0               0               1               FSP HDR
1               1               1               INSERT BUFFER BITMAP
2               2               1               INDEX NODE PAGE
3               3               1               SYSTEM PAGE
4               4               1               INDEX PAGE
5               5               1               TRX SYSTEM PAGE
6               7               2               SYSTEM PAGE
8               8               1               SDI INDEX PAGE
9               12799           12790           FRESHLY ALLOCATED PAGE

打开一个普通的用户表空间, 可以看到如下的结构.

└─[$] ./inno -f ~/git/primary/dbs2250/sbtest/sbtest1.ibd -c list-page-type
File path /home/zongzhi.czz/git/primary/dbs2250/sbtest/sbtest1.ibd path, page num 0
page num 0
==========================space page type==========================
File size 2604662784
start           end             count           type
0               0               1               FSP HDR
1               1               1               INSERT BUFFER BITMAP
2               2               1               INDEX NODE PAGE
3               3               1               SDI INDEX PAGE
4               16383           16380           INDEX PAGE
16384           16384           1               XDES
16385           16385           1               INSERT BUFFER BITMAP
16386           31990           15605           INDEX PAGE
31991           31999           9               FRESHLY ALLOCATED PAGE
32000           32767           768             INDEX PAGE
32768           32768           1               XDES
32769           32769           1               INSERT BUFFER BITMAP
32770           49151           16382           INDEX PAGE
49152           49152           1               XDES
49153           49153           1               INSERT BUFFER BITMAP
49154           65535           16382           INDEX PAGE
65536           65536           1               XDES
65537           65537           1               INSERT BUFFER BITMAP
65538           81919           16382           INDEX PAGE
81920           81920           1               XDES

下一篇物理页管理我们会更详细的介绍.

File Per Table

InnoDB 常见的file per table 模式下. 一个table 对应一个.ibd 文件.

page 0, 1, 2 这3个page 所有的space file 都一样

page 3 一般是 primary index root page.

page 4 一般是 secondary index root page. 当然这里是create table 就指定的时候, 比如如下 page 4 一般是k_1 这个index 的root page

Create Table: CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=237723 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

如果后面运行过程中再加的新的 secondary index, 新的Index的root page 那就不会是连续着的, 而是分散在其他page 上了

alter table sbtest1 add index idx_c(c);

比如执行alter table 以后, 额外增加的一个index, 通过inno_space 工具可以看到每一个index 的root page 所在等等

Example 2:
./inno -f ~/git/primary/dbs2250/sbtest/sbtest1.ibd -c index-summary
File path /home/zongzhi.czz/git/primary/dbs2250/sbtest/sbtest1.ibd path, page num 0
==========================Space Header==========================
Space ID: 15
Highest Page number: 158976
Free limit Page Number: 152256
FREE_FRAG page number: 24
Next Seg ID: 7
File size 2604662784
========Primary index========
Primary index root page space_id 15 page_no 4
Btree hight: 2
<<<Leaf page segment>>>
SEGMENT id 4, space id 15
Extents information:
FULL extent list size 2140
FREE extent list size 0
PARTIALLY FREE extent list size 1
Pages information:
Reserved page num: 137056
Used page num: 137003
Free page num: 53

<<<Non-Leaf page segment>>>
SEGMENT id 3, space id 15
Extents information:
FULL extent list size 1
FREE extent list size 0
PARTIALLY FREE extent list size 1
Pages information:
Reserved page num: 160
Used page num: 116
Free page num: 44

========Secondary index========
Secondary index root page space_id 15 page_no 31940
Btree hight: 2
<<<Leaf page segment>>>
SEGMENT id 6, space id 15
Extents information:
FULL extent list size 7
FREE extent list size 0
PARTIALLY FREE extent list size 219
Pages information:
Reserved page num: 14465
Used page num: 12160
Free page num: 2305

<<<Non-Leaf page segment>>>
SEGMENT id 5, space id 15
Extents information:
FULL extent list size 0
FREE extent list size 0
PARTIALLY FREE extent list size 0
Pages information:
Reserved page num: 19
Used page num: 19
Free page num: 0

**Suggestion**
File size 2604662784, reserved but not used space 39354368, percentage 1.51%
Optimize table will get new fie size 2565308416
  1. 这里tablespace id 是15
  2. Btree 的高度是3层
  3. secondary Index 由于只存索引, 所以primary index 占用的空间是secondary index 的10倍
  4. primary Index 上面大量的page 都是用满的状态, 而secondary 会20% 左右的空闲page
  5. 整体而言, 空闲page 只占了文件的1.51% 左右, 所以不需要做optimize table 操作的
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3月前
|
存储 网络协议 关系型数据库
MySQL8.4创建keyring给InnoDB表进行静态数据加密
MySQL8.4创建keyring给InnoDB表进行静态数据加密
99 1
|
5月前
|
存储 SQL 关系型数据库
MySQL底层概述—2.InnoDB磁盘结构
InnoDB磁盘结构主要包括表空间(Tablespaces)、数据字典(Data Dictionary)、双写缓冲区(Double Write Buffer)、重做日志(redo log)和撤销日志(undo log)。其中,表空间分为系统、独立、通用、Undo及临时表空间,分别用于存储不同类型的数据。数据字典从MySQL 8.0起不再依赖.frm文件,转而使用InnoDB引擎存储,支持事务原子性DDL操作。
376 100
MySQL底层概述—2.InnoDB磁盘结构
|
2月前
|
canal 关系型数据库 MySQL
MySQL 自动同步开源工具
本文介绍了几种开源工具用于实现 MySQL 数据库的自动同步。
|
5月前
|
SQL 关系型数据库 MySQL
MySQL底层概述—10.InnoDB锁机制
本文介绍了:锁概述、锁分类、全局锁实战、表级锁(偏读)实战、行级锁升级表级锁实战、间隙锁实战、临键锁实战、幻读演示和解决、行级锁(偏写)优化建议、乐观锁实战、行锁原理分析、死锁与解决方案
268 24
MySQL底层概述—10.InnoDB锁机制
|
3月前
|
SQL 缓存 关系型数据库
使用温InnoDB缓冲池启动MySQL测试
使用温InnoDB缓冲池启动MySQL测试
68 0
|
5月前
|
存储 缓存 关系型数据库
MySQL底层概述—5.InnoDB参数优化
本文介绍了MySQL数据库中与内存、日志和IO线程相关的参数优化,旨在提升数据库性能。主要内容包括: 1. 内存相关参数优化:缓冲池内存大小配置、配置多个Buffer Pool实例、Chunk大小配置、InnoDB缓存性能评估、Page管理相关参数、Change Buffer相关参数优化。 2. 日志相关参数优化:日志缓冲区配置、日志文件参数优化。 3. IO线程相关参数优化: 查询缓存参数、脏页刷盘参数、LRU链表参数、脏页刷盘相关参数。
212 12
MySQL底层概述—5.InnoDB参数优化
|
5月前
|
存储 SQL 关系型数据库
MySQL底层概述—4.InnoDB数据文件
本文介绍了InnoDB表空间文件结构及其组成部分,包括表空间、段、区、页和行。表空间是最高逻辑层,包含多个段;段由若干个区组成,每个区包含64个连续的页,页用于存储多条行记录。文章还详细解析了Page结构,分为通用部分(文件头与文件尾)、数据记录部分和页目录部分。此外,文中探讨了行记录格式,包括四种行格式(Redundant、Compact、Dynamic和Compressed),重点介绍了Compact行记录格式及其溢出机制。最后,文章解释了不同行格式的特点及应用场景,帮助理解InnoDB存储引擎的工作原理。
MySQL底层概述—4.InnoDB数据文件
|
5月前
|
存储 缓存 关系型数据库
MySQL底层概述—3.InnoDB线程模型
InnoDB存储引擎采用多线程模型,包含多个后台线程以处理不同任务。主要线程包括:IO Thread负责读写数据页和日志;Purge Thread回收已提交事务的undo日志;Page Cleaner Thread刷新脏页并清理redo日志;Master Thread调度其他线程,定时刷新脏页、回收undo日志、写入redo日志和合并写缓冲。各线程协同工作,确保数据一致性和高效性能。
MySQL底层概述—3.InnoDB线程模型
|
21天前
|
人工智能 运维 关系型数据库
数据库运维:mysql 数据库迁移方法-mysqldump
本文介绍了MySQL数据库迁移的方法与技巧,重点探讨了数据量大小对迁移方式的影响。对于10GB以下的小型数据库,推荐使用mysqldump进行逻辑导出和source导入;10GB以上可考虑mydumper与myloader工具;100GB以上则建议物理迁移。文中还提供了统计数据库及表空间大小的SQL语句,并讲解了如何使用mysqldump导出存储过程、函数和数据结构。通过结合实际应用场景选择合适的工具与方法,可实现高效的数据迁移。
154 1
|
2月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!

推荐镜像

更多