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

!!!

相关推荐
不光头强2 小时前
Spring框架的事务管理
数据库·spring·oracle
百***92024 小时前
【MySQL】MySQL库的操作
android·数据库·mysql
q***76664 小时前
Spring Boot 从 2.7.x 升级到 3.3注意事项
数据库·hive·spring boot
信仰_2739932434 小时前
Redis红锁
数据库·redis·缓存
人间打气筒(Ada)4 小时前
Centos7 搭建hadoop2.7.2、hbase伪分布式集群
数据库·分布式·hbase
心灵宝贝4 小时前
如何在 Mac 上安装 MySQL 8.0.20.dmg(从下载到使用全流程)
数据库·mysql·macos
想睡hhh4 小时前
mysql索引——理解索引机制及操作
mysql
剑动山河5 小时前
ubuntu 升级mysql由mysql5.7.42 升级到8.4.0
mysql·ubuntu·adb
奋斗的牛马5 小时前
OFDM理解
网络·数据库·单片机·嵌入式硬件·fpga开发·信息与通信
忧郁的橙子.6 小时前
一、Rabbit MQ 初级
服务器·网络·数据库