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

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

创建新表页的信息

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
在这里插入图片描述

新增一条数据

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

根据地址计算页号

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)))

根据页号计算起始地址

page_no = 23502
print(hex(page_no * page_size_bytes))

!!!

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三书yjy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值