MySQL_内存
MySQL_内存
Buffer Pool
目的:提高数据库的读写性能。
位置:在InnoDB存储引擎中。
读、改数据的顺序:
- 数据如果在Buffer Pool中,客户端直接读取Buffer Pool中的数据,否则去磁盘中读取。
- 修改数据时,先修改Buffer Pool中数据所在的页16KB,将其设置为脏页,最后由后台线程将脏页写入到磁盘。
缓存什么:
索引页、数据页、插入缓存、undo页、自适应哈希索引、锁信息。
怎么管理:
InnoDB为每一个缓存页都创建了一个控制块,包括(缓存页的表空间,页号,缓存页地址,链表节点等等)
控制块的位置:在Buffer Pool的最前面,接着才是缓存页。
如何管理Buffer Pool
如何管理空闲页
Free链表(空闲链表):将空闲缓存页的控制块作为链表的节点。
Free链表还有一个头节点,包含(链表的头节点地址,尾节点地址,当前链表中节点的数量等信息)
提高了读性能。
如何管理脏页
Flush链表:链表元素都是脏页。
提高了写性能。
如何提高缓存命中率
改进版LRU算法。
Buffer Pool中有3种页和链表管理数据:
- Free Page,位于Free链表。
- Clean Page,位于LRU链表。
- Dirty Page,同时位于LRU链表和Flush链表。(刷盘后,就变成了Clean Page,所以位于LRU链表)
普通LRU算法的问题:
- 预读失败。(MySQL加载数据页时,会提前把它相邻的数据页一并加载进来,目的是为了减少磁盘IO)预读失败就是被提前加载进来的数据页,并没有被访问。
解决:LRU分成2部分(old区域和young区域)(innodb_old_blocks_pct
可以设置old-young比例)预读的页只加入old区域的头部,页真正被访问(读取页里的记录)的时候,才将页插入young区域的头部。 - Buffer Pool污染。一个SQL语句扫描了大量的数据时,Buffer Pool种所有的页都替换出去,导致大量热数据被淘汰了。(比如全表扫描)
解决:old进入young的条件增加一个停留在old区域的时间判断。大于这个时间间隔innodb_old_blocks_time
才放入young区域。
脏页什么时候刷盘
WAL技术,先写日志,再刷盘。
- redo loh日志满了。
- Buffer Pool空间不足。淘汰一部分数据页,如果淘汰的是脏页,则刷盘。
- MySQL认为空闲时,后台线程刷盘。
- MySQL正常关闭之前。
三种List总结
- Free List 管理空闲页
- Flush List 管理脏页
- LRU List 管理脏页+干净页。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)