【MySQL】好好学习一下InnoDB中的页
文章目录
- 一. 前言
- 二. 从宏观层面看页
- 三. 页的基本内容
- 3.1 页的数据结构
- 3.2 用户空间内的数据行结构
- 3.3 页目录
- 四. 问题集
- 4.1 索引 和 数据页 有什么区别
- 4.2 页的大小是什么决定的
- 4.3 页的大小对哪些情况有影响
- 4.4 一般情况下说的链表有哪几个
- 4.5 如果页的空间满了怎么办
- 4.6 如果页的空间空了怎么办
- 4.7 删除的数据何时被清理
- 4.8 数据页和B+树及索引的关系
- 总结
- 附录
- 参考文档
一. 前言
周末没啥计划,把大佬的<MySQL是怎样运行的>又翻了出来,重新学习一下页的概念。
页这个东西,看起来不怎么显眼,但是深层的东西都会碰到他,又爱又恨,逼着人必须弄懂。
二. 从宏观层面看页
高并发里面有一种提高性能的思路是 :通过批处理一次性处理大量数据,避免频繁的网络流量和IO。
MySQL 的页就是基于这种概念,磁盘是存放数据的载体,而数据处理会发生了内存中,所以流程大致分为:
- S1 : 首先对数据进行切分,划分成若干页
- S2 : 每次读取的时候,都直接把一整页读取到内存中
- S3 : 外部读取的时候,直接对内存中的数据进行读取和操作
- S4 : 如果发生了修改操作,需要把内存的内容刷新到磁盘上
页的好处
这里比较模糊的是为什么要衍生出一个页,而不是通过行级别进行处理。
- 首先解决的就是 IO 问题,当然如果说每个页只读一条,那么这种就不算优势,但是我们大批量读取的时候,往往是查询连续的数据 , 相对而言取舍后,效率就更高了。
- 避免碎片化,行的级别太低了,大小也不同,使用行的时候,存储空间不便于分配
- 提高并发和锁,可以通过控制事务到一个页里面,减少事务的粒度
- 提高维护性和通用性 ,当发生重整时,页的处理会更简单
三. 页的基本内容
页的概念与索引关联的概中主要包括 :
- 页 (Page): 页是数据存储的基本单位,是一个固定大小的数据块,通常是16K
- 行 (Row): 行是数据库中的基本数据单位 ,代表表中的一个记录
- 分组(Group):将一个页里面除了删除的记录进行逻辑划分,取每组最后一条记录作为偏移量标志位
- 槽(Slot):每个分组的最后一条数据会在页目录里面作为一个指针存在,这个指针就是一个槽
页目录 (Page Directory):用来管理数据页的一种数据结构,目录内记录了指针,索引等位置信息
3.1 页的数据结构
- File Header 和 Page Header 包含了该页的基础属性和状态信息等
- Infimum / Supremum 是虚拟的行记录,用于限定记录的边界,他们都是虚拟的,不表示任何存在
- Infimum 标识比该页任何值都要小的值
- Supremum 标识比该页任何值都要大的值
- 用户记录和空闲记录是实际的存储空间,随着插入数据空闲空间会越来越小
- 页面目录用来存储记录的相对位置,通过稀疏目录的方式加快了查询的数据
- File Trailer 目的是为了保证数据的完整性,其中会存放一个校验和保证数据是正确的
插入数据带来的结构变化
3.2 用户空间内的数据行结构
其中主要的参数是 :
- n_owned:当前记录拥有的记录数 ,通过该数据来确定每组数据的大小
- heap_no:当前记录在堆的位置,最小和最大的heap_no 分别是 0,1 ,标识在最上面
- next_record:下一记录的相对位置 , 用于保证数据成一个链表结构
3.3 页目录
我们或多或少都接触过数组或者集合,对于数组的查询方式有很多,正序或者逆序,或者效率更高的二分法
前提 : MySQL 的数据按照行记录进行存储,在一个表中,行的数据是有序的
目录 :但是不论多么优良的算法,在大数据量的场景下,还是会有很高的性能损耗,而 MySQL 为了解决这种场景,采取的是目录的方式。 目录中通过槽和分组,得到了一个数据的精简模型,通过精简的数据快速查询对应的分组,再在分组里面进行循环查找
槽和分组
有个资料里面说的是一个数据行就对应一个槽,也有说多个记录一个槽,我这里倾向于后一种说法,即稀疏目录。
页目录存放了记录的相对位置,每个相对位置即为一个槽,在InnoDB 里面是使用稀疏目录 (sparse directory), 即一个槽会属于多个记录 (4-8条)
-
最小记录的条数是1
-
最大记录所在分组的记录数是1-8
-
其他分组在 4-8之间
-
指向原理
- 查询数据时,首先通过二分法在页目录中进行查询
- 当查询到分组范围后,再通过分组里面的 next_record 查询具体的数据
四. 问题集
4.1 索引 和 数据页 有什么区别
- 两者不是同一个东西,存储的数据和结构都不同
- 在索引中,每一个 B+树节点对应一个索引页,一个索引页中存储索引键值和指向指针
- 数据查询时,通过根索引页开始,遍历索引树,从而拿到指向数据行的指针
- InnoDB 会通过索引中的数据行指针定位到数据页 (直接通过物理地址指向槽号)
除了这些页,InnoDB 中还有存放表空间头部信息的页,Buffer 页等。
4.2 页的大小是什么决定的
- 页的大小是由创建数据库表时指定的存储参数 innodb_page_size 决定的
- 参数一旦设置就不能更改,不然就得刷页里面大量的数据
CREATE TABLE my_table (...) ENGINE = InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8 PAGE_COMPRESSED=1 PAGE_SIZE=64K;
4.3 页的大小对哪些情况有影响
- 索引效率 :前面说了,索引过程中会通过每页的最大最小进行快速匹配,而较大的页一定程度上会使相同数据量情况下拥有更少的页,从而降低索引节点的数量,索引树高度也因此降低。查询效率会有所提高
- 内存占用 :较大的页会在内存中占用更多的空间。因为读取时,每次都是读取一整页,所以内存每次读取得更多。
- 其他硬件影响 :更大的页会影响磁盘IO和CPU,IOPS 方面都会带来更多的压力
总结 :提高效率,但是增加了系统负载。
4.4 一般情况下说的链表有哪几个
一个列里面的数据行之间通过 next_record 形成的单向链表
上文说到了每个数据行上面会有个 next_record 参数,该参数记录了真实数据达到下一条记录的真实数据的偏移量,这里有几点值得注意 :
- 这里的顺序不是插入数据,而是主键值由小到大的顺序
- 上一条指向的是下一条的value的位置,而不是 Header 头的位置
不同数据页之间组成的双向链表
上面的结构图看过了,每个页里面都会包含 File Header 和 Page Header 两个对象。
- Page Header : 记录当前页的状态信息和规则,例如槽数,记录数,剩余空间数等等
- File Header : 记录当前页的标准信息,包括页的编号,页所在的表空间,上一页页号和下一页页号
而**双向成方式不言而喻,都知道上页 (FIL_PAGE_PREV) 和 下页(FIL_PAGE_NEXT)的页号了,那访问完全没问题了 , 由于都只存了上一个和下一个,也就形成了标准的链表结构。
补充 : 上面看到的这种通常是指 LRU 链表,还有一个双向链表是 Flush List (刷新链表),这个链表是在数据页发生修改后,使用刷新链表可以让数据按照一定的顺序刷新到磁盘上
4.5 如果页的空间满了怎么办
- 首先,页的的大小是在存储引擎创建的时候就确定了,所以空间固定。
- 其次页内数据是按照主键进行排序,所以这个时候插入铁定空间超了
在这种场景下,会触发页分裂 ,此时 InnoDB 会执行下列操作 :
- S1 : 创建新的数据页
- S2 : 按照排序方式将部分数据迁移到新页
- S3 : 更新上下页关系和对应的索引关系
这里由于页是双向链表进行的关联,所以插入并不会对数据结构进行大的破坏,只需要对应的上下页进行更新就行了。
4.6 如果页的空间空了怎么办
既然会有页分裂,那就有可能会出现分裂的页不均衡的情况,长时间下去,就会形成很多空闲块,这样的结构也是不合理的,不仅会占用不必要的空间,还会导致查询性能降低。
为了避免这些问题,InnoDB 会有页合并的功能 , 原理和上面的类型。相邻页尝试合并,然后重新更新引用和索引。
4.7 删除的数据何时被清理
之前看到了数据被删除后,其目录数据里面的 delete_mask 会被置为已删除。
此时的数据处在逻辑删除的状态,通过上面说的 next_record (下一记录的相对位置)指向后续存在的正常数据。
这样做的目的主要是避免碎片,提高删除的性能(只需要修改标识和引用),同时保证了删除的事务。
但是长此以往就会有大量的删除数据占用空间,为了避免这种情况,InnoDB 会定期的进行清理,同时重新整理数据页。
4.8 数据页和B+树及索引的关系
-
数据页是为了存储数据行的,存放的是二进制数据,通常数据行按照主键的顺序存放
-
B+树是一种数据结构,也是索引的结构,B+树结构让索引更加有效和便于管理
-
索引中的B+树叶子节点存储了索引条目,每个条目对应一个数据行的物理指针(通常是数据行的槽号)
- 当获得槽号后,就直接通过槽号读取想要的数据,并且返回
页和索引是相辅相成的,如果没有索引,页就需要在单向链表里面向下寻找,直到找到对应的数据
总结
页是存储的基础,也是索引的基础,了解了页后面就可以深入的了解索引了。
这一块没了解太深,毕竟这东西其实我应用的场景几乎没有,主要是不弄清楚后面读起来很难受。
尽量做到了自己去输出东西,整理了一些问题,但是毕竟站在别人修好的路上面,有些东西不能保证一定是对的,也有可能是我理解有误,如果有问题建议去看原文或者官方文档。
附录
头部信息对于我们日常业务中几乎是没太大用的,这里只记录几个我认为和上文有一定关联的参数 :
-
页头部信息
- PAGE_N_DIR_SLOTS : 页目录中的槽数量
- PAGE_N_HEAP : 本页中的记录数量
- PAGE_GARBAGE : 已删除记录中的字节数
- PAGE_LAST_INSERT :最后插入记录的位置
- PAGE_DIRECTION :记录插入的方向
- PAGE_N_RECS : 该页中记录的数量
- PAGE_LEVEL : 当前页在 B+树中所处的层级
- PAGE_INDEX_ID : 索引ID
-
文件头部信息
- FIL_PAGE_OFFSET : 页号
- FIL_PAGE_PREV : 上一个页的页号
- FIL_PAGE_NEXT : 下一个页的页号
- FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID : 页属于哪个表空间
参考文档
-
小册 : MySQL是怎样运行的
-
MySQL 技术内幕
相关文章:

【MySQL】好好学习一下InnoDB中的页
文章目录 一. 前言二. 从宏观层面看页三. 页的基本内容3.1 页的数据结构3.2 用户空间内的数据行结构3.3 页目录 四. 问题集4.1 索引 和 数据页 有什么区别4.2 页的大小是什么决定的4.3 页的大小对哪些情况有影响4.4 一般情况下说的链表有哪几个4.5 如果页的空间满了怎么办4.6 如…...
git开发常用命令
版本回退 soft:git reset --soft HEAD^ 将版本库回退一个版本,且这次提交的所有文件都移动到暂存区 mixed(默认):git reset HEAD^ 将版本库回退一个版本,且这次提交的所有文件都移动到工作区,会…...

WEB APIs day5
一、window对象 BOM属于window对象 1.BOM(浏览器对象模型) bom里面包含着dom,只不过bom我们平时用得比较少,我们经常使用的是dom操作,因为我们页面中的这些标签都是在dom中取的,所以我们操作dom多一点。 window对象…...

html动态爱心代码【一】(附源码)
前言 七夕马上就要到了,为了帮助大家高效表白,下面再给大家带来了实用的HTML浪漫表白代码(附源码)背景音乐,可用于520,情人节,生日,表白等场景,可直接使用。 效果演示 文案修改 var loverNam…...

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数
线程池改造 上一篇文章中我们用了Excutors创建了线程,这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…...

Android Studio 接入OpenCV最简单的例子 : 实现灰度图效果
1. 前言 上文 我们在Windows电脑上实现了人脸功能,接下来我们要把人脸识别的功能移植到Android上。 那么首先第一步,就是要创建一个Native的Android项目,并且配置好OpenGL,并能够调用成功。 这里我们使用的是openCV-4.8.0&#x…...
(1)、扩展SpringCache一站式解决缓存击穿,穿透,雪崩
1、问题描述 我们在使用SpringCache的@Cacheable注解时,发现并没有设置过期时间这个功能。 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @I...

Rancher使用cert-manager安装报错解决
报错: rancher-rke-01:~/rke/rancher-helm/rancher # helm install rancher rancher-stable/rancher --namespace cattle-system --set hostnamewww.rancher.local Error: INSTALLATION FAILED: Internal error occurred: failed calling webhook "webhook…...

Harvard transformer NLP 模型 openNMT 简介入门
项目网址: OpenNMT - Open-Source Neural Machine Translation logo: 一,从应用的层面先跑通 Harvard transformer GitHub - harvardnlp/annotated-transformer: An annotated implementation of the Transformer paper. git clone https…...

【数据结构OJ题】用栈实现队列
原题链接:https://leetcode.cn/problems/implement-queue-using-stacks/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 用两个栈实现,一个栈进行入队操作,另一个栈进行出队操作。 出队操作: 当出队的栈…...

通达信指标公式15:除权除息数据统计分析
#1.关于除权除息指标的介绍:本指标是小红牛原创指标之一,觉得有必要研究一下这个问题,所以就花时间整理一下这个指标相关内容,大家可以在本源码基础上,进一步优化自己的思路。本指标为通达信幅图指标,可以做…...

day-27 代码随想录算法训练营(19)回溯part03
39.组合总和 分析:同一个数可以选多次,但是不能有重复的答案; 思路:横向遍历,纵向递归(不同的是递归的时候不需要跳到下一个位置,因为同一个数可以选多次) class Solution { publ…...
CSDN编程题-每日一练(2023-08-22)
CSDN编程题-每日一练(2023-08-22) 一、题目名称:最长递增区间二、题目名称:K树三、题目名称:小Q的价值无向图一、题目名称:最长递增区间 时间限制:1000ms内存限制:256M 题目描述: 给一个无序数组,求最长递增的区间长度。如:[5,2,3,8,1,9] 最长区间 2,3,8 长度为 3。…...

使用 KubeBlocks 为 K8s 提供稳如老狗的数据库服务
原文链接:https://forum.laf.run/d/994 大家好!今天这篇文章主要向大家介绍 Sealos 的数据库服务。在 Sealos 上数据库后端服务由 KubeBlocks 提供,为用户的数据库应用保驾护航。无论你是在公有云还是本地环境中使用,Sealos 都能为…...

SFL212B-10-21-15、SFL212B-20-21-40喷嘴挡板伺服阀
SFL212B-05-21-10、SFL212B-10-21-15、SFL212B-20-21-40、SFL212-05-32-10、SFL212-10-32-15、SFL212-20-32-40、SFL212A-05-21-10、SFL212A-10-21-15、SFL212A-20-21-40喷嘴挡板力反馈伺服阀,外置伺服放大器,四通,带阀芯阀套的两级伺服阀&am…...

阿里云100元预算可选的云服务器配置2核2G3M带宽
阿里云服务器100元可以买到哪些配置?如果是一年时长,轻量应用服务器2核2G3M带宽一年108元,系统盘为50GB高效云盘。以前阿里云服务器ECS卖过35元一年、69元、88元、89元和99元的都有过,但是现在整体费用上涨,入门级云服…...

Linux问题--docker启动mysql时提示3306端口被占用
问题描述: 解决方法: 1.如果需要kill掉mysqld服务可以先通过 lsof -i :3306 2. 查询到占用3306的PID,随后使用 kill -15 PID 来kill掉mysqld服务。 最后结果...

2023年中秋月饼市场趋势分析(月饼京东销售数据分析)
中秋将至,月饼作为节令食品将再次掀起消费热潮。今年月饼市场的需求如何呢,是更受欢迎还是热度有所降低,结合数据我们一起来看今年月饼市场的销售表现。 在这里,我们分别选取了2022年第31周-32周和2023年第31周-32周(…...
A Survey on Model Compression for Large Language Models
本文是LLM系列文章,关于模型压缩相关综述,针对《A Survey on Model Compression for Large Language Models》的翻译。 大模型的模型压缩综述 摘要1 引言2 方法3 度量和基准3.1 度量3.2 基准 4 挑战和未来方向5 结论 摘要 大型语言模型(LLM…...
读取/加载 properties/yml 配置文件
大家好 , 我是苏麟 , 今天带来一个简单好用的东西 . 读取/加载 properties/yml配置文件 基于PropertiesConfiguration读取配置文件 引入依赖 <!--加载yml资源--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-b…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...