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

!!!

相关推荐
jiunian_cn4 分钟前
【Linux】Linux权限
linux·服务器·mysql
betazhou26 分钟前
有没有 MariaDB 5.5.56 对应 MySQL CONNECTION_CONTROL 插件
linux·数据库·mysql·oracle·mariadb
Elohim81532 分钟前
数据库SQLite基础
数据库·sqlite
TDengine (老段)43 分钟前
TDengine 支持的平台汇总
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
异常君44 分钟前
MySQL 中 count(*)、count(1)、count(字段)性能对比:一次彻底搞清楚
java·mysql·面试
烟雨书信1 小时前
Linux中MySQL的逻辑备份与恢复
linux·运维·mysql
大熊猫侯佩1 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(四)
数据库·swiftui·apple watch
想用offer打牌2 小时前
面试官问:Redis和MySQL数据一致,为什么还需要MySQL?🤠
数据库·redis·mysql
chen.@-@2 小时前
后端下载限速(redis记录实时并发,bucket4j动态限速)
数据库·redis·缓存
王小小鸭2 小时前
【Oracle APEX开发小技巧12】
数据库·oracle