三、MySQL整体概述 之缓冲池(Buffer Pool)

MySQL缓冲池详解:原理与优化
本文介绍了MySQL缓冲池(Buffer Pool)的作用、结构及其重要组件,包括数据页、缓冲池大小设置、数据页加载、LRU链表、flush链表、预读机制和优化策略。缓冲池通过内存缓存提升数据库性能,避免频繁磁盘I/O。讨论了如何通过多Buffer Pool和动态调整大小来优化并发能力和资源利用。

MySQL整体概述 之缓冲池(Buffer Pool)

文章非原创,属于对以往学习到的知识的归纳总结,文中可能存在大段截取其他文章的片段,博客属于自我学习的笔记总结会持续更新。。。

一、缓冲池
我们知道数据库数据最终是存到磁盘上的,但是我们操作数据的时候如果直接操作磁盘进行随机的读写操作,速度会很慢,最终拖慢你处理请求的能力。因此我们的增删改操作主要针对内存数据执行。

二、缓冲池结构
在这里插入图片描述
1.设置缓冲池的大小
缓冲池默认的大小为128M,在实际的生产环境中一般建议设计为机器内容空间的60%,假如在16核32G的机器下我们可以给他分配2G的内存,那么我们如下配置即可。

[server]
innodb_buffer_pool_size = 2147483648

2.数据页
是mysql抽象出来的数据概念,MySQL把许多行数据放在数据页里。磁盘中的数据页默认大小为16KB,缓冲池中的数据页我们称之为缓冲页,它默认跟数据页是一一对应的关系因此也是16KB,但是缓冲页存在一个描述数据(元数据),里面包含:这个缓冲页所属的表空间,数据页编号,在缓冲池中的地址等。这些描述数据大概数据页大小的5%800个字节左右,所以缓冲池的实际大小是大于128M的大概在130M 左右。缓冲池大小为128M数据页大小为16kb描述数据大小为800个字节,在分配空间存放缓存页的时候肯定存在一些内存碎片。
注意:在SQL语句中我们只关心表、列、行这些都是逻辑概念,但表中数据库磁盘中就是按照数据页来存放的 这个就是物理概念了。
3.数据页的加载
缓冲池初始分配好空间之后,内部的缓冲页都是空。数据库运行,开始进行增删查改操作,需要先将磁盘上的数据页加载进缓冲池中,那它怎么知道应该加载到哪个缓存页中呢?(肯定是需要加载到空白缓存页中,但是加载的时候它怎么知道哪个缓存页是空的呢?)在数据库会为Buffer Pool设计一个free链表,该链表并不是额外重新分配出来一个空间单独维护一个表,而是将空白的缓存页对应的描述数据(元数据)相关联形成一个双向链表,所以在这个链表中每个节点就是一个缓冲页的描述数据的地址,因此只要一个缓存页是空闲的,那么他的描述数据块就会被放入这个free链表中。(但是在free链表中还有一个基础节点大约是40个字节左右是不属于Buffer Pool的,它里面存放的是一个开始节点的地址,一个结束节点的地址,以及表中存放的节点的个数。)
有了free链表 从表里获取一个描述数据块,然后就可以对应的获取到这个描述数据块对应的空闲缓存页,接着我们就可以把磁盘上的数据页读取到对应的缓存页里去,同时把相关的一些描述数据写入缓存页的描述数据块里去,比如 这个数据页所属的表空间之类的信息,最后把那个描述数据块从fr

MySQL(特别是 InnoDB 存储引擎)中,**Change Buffer** 和 **Buffer Pool** 都是用于提升性能的内存结构,但它们的作用范围和机制有所不同。 --- ### ✅ Buffer Pool缓冲池) - **作用**: Buffer Pool 是 InnoDB 最主要的内存缓存区域,用来缓存**数据页和索引页**,减少磁盘 I/O。 - **工作方式**: - 当查询需要读取某个数据页时,InnoDB 会先检查该页是否在 Buffer Pool 中; - 如果存在(命中),直接从内存读取; - 如果不存在(未命中),则从磁盘加载到 Buffer Pool 中再使用。 - **特点**: - 缓存的是实际的数据页(如聚簇索引页、二级索引页等); - 大小由 `innodb_buffer_pool_size` 参数控制; - 使用 LRU 算法管理内存淘汰; - 对所有类型的读写操作都有加速作用。 ```sql -- 查看 Buffer Pool 大小(默认单位是字节) SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; ``` --- ### ✅ Change Buffer(变更缓冲区) - **作用**: Change Buffer 主要用于优化**对非唯一二级索引页的写操作**(INSERT、UPDATE、DELETE),当这些页**不在 Buffer Pool 中时**,避免立即从磁盘读取该页。 - **工作方式**: - 当修改一个**不在内存中的二级索引页**时,InnoDB 不直接读取该页,而是将这个修改操作记录在 Change Buffer 中; - 后续当该页被加载进 Buffer Pool 时(比如下次查询访问到它),再将 Change Buffer 中的修改“合并”到该页上; - 这个过程称为 **merge**。 - **适用场景**: - 只适用于**非唯一的二级索引**(因为唯一索引必须实时校验唯一性,不能延迟); - 在高并发写入场景下能显著减少随机 I/O。 - **配置参数**: ```sql -- 查看当前 change buffer 的配置 SHOW VARIABLES LIKE 'innodb_change_buffering'; SHOW VARIABLES LIKE 'innodb_change_buffer_max_size'; ``` - `innodb_change_buffer_max_size`:表示 Change Buffer 最大可占用 Buffer Pool 的百分比,默认为 25%(即最多占 1/4)。 --- ### 🔁 两者关系与区别 | 特性 | Buffer Pool | Change Buffer | |------|-------------|---------------| | 类型 | 主数据缓存区 | 辅助写优化结构 | | 缓存内容 | 数据页、索引页 | 对不在内存中的二级索引的**写操作日志** | | 作用对象 | 所有页 | 主要是非唯一的二级索引页 | | 是否在内存中 | 是(属于内存结构) | 是(Change Buffer 本身也在 Buffer Pool 内部) | | 目的 | 减少读 I/O | 减少写 I/O(延迟写入) | | 工作时机 | 读/写时 | 写时记录,读或加载时合并 | > ⚠️ 注意:Change Buffer 实际上是 **Buffer Pool 的一部分**,它并不是独立于 Buffer Pool 的内存区域。 --- ### 📈 工作流程示例 ```sql -- 假设我们有一个表,带有一个非唯一二级索引 key_col UPDATE users SET key_col = key_col + 1 WHERE id = 100; ``` 1. 聚簇索引页(主键)通常在 Buffer Pool 中 → 直接修改; 2. 对应的二级索引页如果**不在 Buffer Pool 中**: - InnoDB 不去磁盘读取它; - 而是把“这个索引要加 1”的操作写入 Change Buffer; 3. 下次有人访问这个页时,它被加载进 Buffer Pool; 4. 然后执行 merge:把 Change Buffer 中对该页的操作应用上去。 --- ### 💡 总结 - **Buffer Pool** 是核心缓存,提升整体读写性能; - **Change Buffer** 是针对二级索引写操作的优化机制,通过延迟写入减少随机 I/O; - Change Buffer **依赖 Buffer Pool** 存储其数据; - 合理配置两者可以极大提升 MySQL 写密集型应用的性能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值