MySQL的InnoDB的页里面存了些什么

文章目录

主要介绍表空间索引页里面有哪些内容,数据在表空间文件里面是怎么组织的

创建新表页的信息

sql 复制代码
CREATE TABLE `test8` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT '' COMMENT '姓名',
  `finish` tinyint(1) DEFAULT '0' COMMENT '完成状态',
  `uid` varchar(64) NOT NULL DEFAULT '' COMMENT '用户ID信息',
  `external1` varchar(512) NOT NULL DEFAULT '' COMMENT '大字段信息1',
  `external2` varchar(512) NOT NULL DEFAULT '' COMMENT '大字段信息2',
  `external3` varchar(512) NOT NULL DEFAULT '' COMMENT '大字段信息3',
  `external4` varchar(512) NOT NULL DEFAULT '' COMMENT '大字段信息4',
  `external5` varchar(512) NOT NULL DEFAULT '' COMMENT '大字段信息5',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '缓存时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='测试信息表8';

新建一个测试表test8,然后看看缓冲池里的页的变化。把表test8的一些页加载进来了,看最后一列INDEX_NAME有个PRIMARYidx_name两个索引的名称,一个是主键索引,一个是辅助索引;因为InnoDB是聚簇索引形式的,主键索引的叶子节点就包含了数据。

FILE_SPACE_HEADER页增加了1个,是把test8FILE_SPACE_HEADER页加载进来了,IBUF_BITMAP页多了7个是除了加载了test8的这个页,还加载了其他test数据库下的表进来...

再看这个表空间里面有什么,7个页112k,MySQL初始创建表不是只有96k么?为啥这多了16k;MySQL建一个一般的表确实只给6个页的空间;但是我们这边张表多了个索引,它就给索引也分配了一个页。试了下如果两个索引的话,会多给两个页,就是多几个索引就多几个页。

使用命令hexdump -C test8.ibd输出页格式化的二进制信息;页的类型信息在第25,26两个字节的位置。

截图里面的 * 号代表这一行的数据和上一行一样,省略了

主键索引页和辅助索引页类型的值都是0x45bf,所以他们都是INDEX页,主键索引叶子节点会存放数据,辅助索引就是单纯的辅助索引,要整行数据需要再到主键索引下去找。

所有的页面类型信息,见源码storage/innobase/include/fil0fil.h

新增一条数据

sql 复制代码
INSERT INTO `test8` (`name`, `finish`, `uid`, `external1`, `external2`, `external3`, `external4`, `external5`, `create_time`)
VALUES
	('name001', 0, 'uid001', 'aaaaaaaa', 'bbbbbbbb', 'cccccccc', 'dddddddd', 'eeeeeeee', '2024-08-04 18:09:35');

页还是那么几个,没什么变化,NEWEST_MODIFICATION变化了,这代表LSN号;我们每次提交事务的时候,数据都会刷新到redo log里面,会有这个日志序列号LSN,代表页面有变化了;行数就像我们看到的1行,数据的大小变了。

LSN在页中的位置是页面类型前面的8个字节,可以自己输出看看文件里面的前8个字节的数转换成十进制是不是这么多。

再用hexdump命令看看test8.ibd文件

主键索引页的大小92个字节:画红线的字节前面7个字节是varchar字符串的这个记录每个信息的长度,逆序存放的的;再后面1个字节是代表哪个位置为null的,后面5个字节是记录头信息;第一个蓝线是主键ID,紧接着是Transaction IDRoll Pointer,最后画红线的是时间字段信息,剩下的看得出来是我们插入的记录,加起来92个字节

辅助索引页的大小21个字节:前面6个字节varchar的长度以及记录头信息,索引字段name0017个字节,主键ID 8个字节,加起来21个字节。

下面我们到一个数据多一点的表里面去找找数据

根据页号找数据信息

我这边前面测试的时候建过一个test2表,插入了上百万条数据,我们看看缓冲池里面加载了些什么数据进来,这是目前在缓冲池里面的页的数据

我们看看页号101的数据是哪些数据,计算出它的起始地址是0x194000,它是一个INDEX页,独立表空间里面基本上都是索引页了;0x1242 的十进制是4674;查询出来就是这条数据了

我们再找个二级索引页,执行下索引列的统计sqlMySQL缓冲池就会把索引页加载进来了

我们看看页号23751的数据是哪些数据,计算出它的起始地址是0x1731c000,它是一个二级索引页(第56-64个字节有值,就是二级索引页,表示修改当前页的最大事务ID,仅在二级索引中定义,聚簇索引没有),独立表空间里面基本上都是数据页了;0x03e7cf 的十进制是255951;查询出来这行数据的索引列就是这个

好了,差不多就写这么多了,还有不少其他不明白的细节,以后再慢慢了解吧!

  1. mysql的有符号正数,为什么最高位是1?

脚本代码

py_innodb_page_info

https://github.com/yjysanshu/py_innodb_page_info

根据地址计算页号

python 复制代码
page_size_bytes = 16 * 1024     # 16k

# hexdump 打印出来的地址
hex_address = "00004010"
address = int(hex_address, 16)

print("页号: " + str(address // page_size_bytes))
print("偏移地址: " + str(hex(address % page_size_bytes)))

根据页号计算起始地址

python 复制代码
page_no = 23502
print(hex(page_no * page_size_bytes))

!!!

相关推荐
冬瓜3121 分钟前
linux-c 使用c语言操作sqlite3数据库-1
数据库·sqlite
夜色呦4 分钟前
现代电商解决方案:Spring Boot框架实践
数据库·spring boot·后端
WangYaolove131427 分钟前
请解释Python中的装饰器是什么?如何使用它们?
linux·数据库·python
我是黄大仙1 小时前
利用飞书多维表格自动发布版本
运维·服务器·数据库·飞书
曾经的三心草1 小时前
Mysql之约束与事件
android·数据库·mysql·事件·约束
宋发元1 小时前
如何使用正则表达式验证域名
python·mysql·正则表达式
WuMingf_1 小时前
redis
数据库·redis
张某布响丸辣1 小时前
SQL中的时间类型:深入解析与应用
java·数据库·sql·mysql·oracle
路遇晚风2 小时前
力扣=Mysql-3322- 英超积分榜排名 III(中等)
mysql·算法·leetcode·职场和发展