文章插图
图片
每个叶子节点都有着一个指向包含下一条(顺序)记录的页的指针,这也是InnoDB可以实现自顶向下的遍历和叶子节点顺序范围扫描的能力基础 。
4 页合并(page merging)当执行数据行删除时,并没有物理删除 , 而是将改行数据标记(flaged)为删除,允许被其他记录声明使用 。
文章插图
图片
当页中删除的记录达到MERGE_THRESHOLD(默认页体积的50%),InnoDB确认最靠近的前后页是否页达到MERGE_THRESHOLD,如果也已经在限定值之下,可以将两个页进行合并优化空间使用 。如上图,当page#5数据小于50%时,由于page#6数据量也是小于50%,因此会进行页合并,合并后,page#6就会变为空页,可以接纳新数据 。
文章插图
图片
文章插图
图片
在delete/update语句操作中都可能会诱发页合并的发生,关联到当前页的相邻页 。如果页合并成功 , 在INFOMATION_SCHEMA.INNODB_METRICS中的index_page_merge_successful将会增加 。
5 页分裂(Page Splits)假设有如下场景,page#10已经被填满时,继续插入数据 , #10没有足够空间去容纳新的记录,根据“下一页”逻辑 , 记录应该由page#11负责,但是页#11也已经满了 。
文章插图
图片
文章插图
图片
这时候的简化逻辑为:
- 创建新页#12;
- 判断当前页(page#10)可以从哪里进行分裂(记录行里面);
- 移动记录行;
- 重新定义页与页之间的关系;
文章插图
图片
新的页#12被创建 。
文章插图
图片
此时的页与页之间的关系为:
- Page #10 will have Prev=9 and Next=12
- Page #12 Prev=10 and Next=11
- Page #11 Prev=12 and Next=13(page#13是后续顺序插入新增的页);
不太清楚这里是否会有疑问 , page#10和page#11虽然都已经写满,但是可能已经存在page#12,并且还有大量剩余空间,为什么不做数据迁移呢?这样不就可以不插入新页而导致大量的空间浪费了吗?
虽然从理论上是可行的,但是在实操中 , 这时候InnoDB就需要先遍历确认next page是否有空余位置,甚至是继续遍历直至找到有空余位置的页 , 然后进行数据迁移,这个操作可能带来大量遍历的时间复杂度以及数据复制的IO操作,因此,方案不可行 。
因此,我们可以总结:页分裂可能发生在执行插入或者更新时,但是可能也会造成页的错位(dislocation),即落入不同的区 。
InnoDB用INFORMATION_SCHEMA.INNODB_METRICS表来跟踪页的分裂数 。可以查看其中的index_page_splits和index_page_reorg_attempts/successful统计 。
当page#12和page#10的数据都低于MERGE_THRESHOLD时 , 这时候可以通过页合并将数据合并回来 。
另一种方式是使用OPTIMIZE重新整理表,可以将大量分布在不同区的页理顺 , 因此,也是一个很重量级和耗时的过程 。
同时,不管是页分裂还是页合并 , InnoDB都会在索引树上加写锁(x-latch) 。在操作频繁的系统中这会是在隐患,可能会导致索引的锁竞争(index latch contention) 。如果表中没有合并和分裂操作(也就是写操作),称之为“乐观(optimistic)”更新 , 只需要使用读锁(S) 。带有合并或者分裂的操作称之为“悲观(pessimistic)”更新,使用写锁(X) 。
【MySQL:InnoDB的页合并与页分裂到底是什么】
推荐阅读
- 创建一个双模式跨运行时的 JavaScript 包,你学会了吗
- Spring非常实用的技巧,你确定知道?
- Java垃圾回收器的工作原理及监视不再使用对象的机制
- 2024 年 17 个提高生产力的 Chrome 扩展程序
- Java新的结构化并行模式入门指南
- SQL应用于LLM的程序开发利器——开源LMQL
- LangChain与Redis合作搞事情!创建提高财务文档分析准确性的工具
- 连接六大场景,小红书「搜索直达」是2024不容错过的流量机会
- 假扮卧底,骗 AI 泄露代码拯救人类?由 AI 开发的 AI 游戏来了
- 通过网站微调的方式可稳定关键词排名