MySQL进阶突击系列(08)年少不知BufferPool核心原理 | 大哥送来三条大金链子LRU、Flush、Free

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 本文深入探讨了MySQL中InnoDB存储引擎的buffer pool机制,包括其内存管理、数据页加载与淘汰策略。Buffer pool作为高并发读写的缓存池,默认大小为128MB,通过free链表、flush链表和LRU链表管理数据页的存取与淘汰。其中,改进型LRU链表采用冷热分离设计,确保预读机制不会影响缓存公平性。文章还介绍了缓存数据页的刷盘机制及参数配置,帮助读者理解buffer pool的运行原理,优化MySQL性能。

今日笔记:“自我完整”的人,不管遇到什么挫折,都能维持一整感觉--我在这儿,我相信自己有能力面对生活的挑战。如果出现挫折,能客观对待,既不归罪别人,也不容易怪罪自己,并且懂的安抚自己的挫败感,同时去寻找资源帮助自己。

相反,“未形成自我或自我破碎”的人,遇到挫折,就会觉得“我”被瓦解了,挫败感非常强烈,需要归罪,甩给其他人。


一、前言背景

二、bufferpool是什么?

2.1 数据在bufferpool 是如何存取的?一行一行数据来加载的吗?

2.2 怎么知道数据页是否在缓存池?

三、bufferpool如何管理这些数据页?

3.1 free链表-可用数据页

3.2 flush链表-脏数据页

3.3 free链表可用数据页不足,如何淘汰缓存页?

3.4 LRU链表-淘汰数据页

3.4.1 InnoDB的预读机制

3.4.2 传统LRU链表

3.4.3 改进型LRU链表-1分为2冷热分离设计

3.5 缓存数据页刷盘机制


一、前言背景

通过前面7篇系列文章,我们已经初步了解MySQL整体架构、三大日志法宝、事务隔离级别、锁、mvcc机制、索引优化等相关领域,然而鲜有人知但非常重要的bufferpool同样值得深入探讨学习。InnoDB高效的读写表现,bufferpool提供内存级别的读写管理能力,功不可没。

本文通过bufferpool的free链表、flush链表、lru链表来详细分析缓存池数据页加载、淘汰、刷盘等多个核心机制,希望对大家理解bufferpool运行原理有些许帮助。

二、bufferpool是什么?

作为MySQL高并发读写核心模块,buffer pool是一块基于内存的数据缓存池,默认大小是128Mb。

show variables like '%buffer_pool%';

如果MySQL服务器内存够大,比如16G、32G,可以考虑适当调整buffer pool大小到2G、4G,充分发挥服务高配置的优势,有效提升MySQL读写性能。

bufferpool的内存区域是一片连续的内存区域,里面就是按数据页来划分管理,可以把它想象为一个个16kb大小的数据块拼装成的128Mb 的缓存池。数据库数据逻辑概念,数据库是库、表、行来划分,习惯性的认为数据读写是一行一行的读取更新。实际上,在MySQL数据存储读写最小单元是【数据页】。

每个数据页大小是16Kb,通过命令查询innodb_page_size参数:show variables like '%page_size%';

这个参数不能在运行时修改,上线运行后不应该再次修改,影响非常大。

此外,MySQL的InnoDB存储引擎,支持bufferpool多实例配置,可以提升并发读写性能。


2.1 数据在bufferpool 是如何存取的?一行一行数据来加载的吗?

数据页在内存划分是紧密相连的,可以有效避免内存碎片。每个数据页里除了存放真实数据外,还有数据页号、所属表空间、在缓存池的地址等描述信息。

此外,在磁盘里也是以一个个数据页为最小单元去存取数据,当数据页被用到的时候,就会被加载到缓存池。

2.2 怎么知道数据页是否在缓存池?

当MySQL需要查询一个数据时,需要先判断该数据对应的数据页是否存在bufferpool。

MySQL有个数据页缓存记录hash表,key=表空间号+数据页号,value是=数据页地址。如果该记录表能找到对应数据页key,说明已缓存到bufferpool。否则就需要从磁盘里加载数据页到bufferpool里。


三、bufferpool如何管理这些数据页?

3.1 free链表-可用数据页

为了记录每个数据页是否空闲,bufferpool设计了一个free链表-双向链表,来记录当前缓存池空闲的数据页。如果某个数据页加载存放了数据,该数据页的描述信息就会从free链表移除。

3.2 flush链表-脏数据页

MySQL给bufferpool缓存池维护一个flush链表,用来记录哪些数据页已经被修改过,需要刷到磁盘的脏数据页。如果某个被数据页被修改过,该数据页的描述信息被加入flush链表的节点。flush链表和free链表几乎是一样的,里面主要存放的也是数据页的描述信息,非常轻巧,没有多少数据冗余。

3.3 free链表可用数据页不足,如何淘汰缓存页?

随着时间推移,bufferpool加载进来的数据页越来越多,最终free链表无可用空闲数据页存放新加载数据。此时需要对缓存里的数据页进行筛选淘汰那些命中率低、缓存价值低的数据页。而缓存命中价值通过另一个链表-LRU链表来记录判断。


3.4 改进型LRU链表-淘汰数据页

LRU,全称是least recently used最近最少使用。LRU链表也是双向链表,和free、flush链表类似,里面也是数据页的描述信息。那InnoDB的改进型LRU链表如何设计,和传统的LRU算法有什么区别?我们先了解read ahead预读机制,和传统LRU链表。

3.4.1 InnoDB的预读机制

InnoDB read ahead预读机制:InnoDB在执行加载某些数据页的时候,认为后期会读到某些数据页,就预先把部分非目标数据页一起加载到bufferpool中。预读机制有2种子类型:线性预读和随机预读。

线性预读:参数innodb_read_ahead_threshold=56,这个参数含义是当顺序加载一个数据区(extent)数据页数量大于56个时,就会把相邻数据区(extent)中的全部数据页预读进来。

随机预读:参数innodb_random_read_ahead是关闭的。如果打开该参数为ON,当在一个数据区随机加载了13个数据页,就直接把该数据区其他数据页全部加载到bufferpool。

综上所述,InnoDB默认情况下,只会触发线性预读。也就是当顺序访问一个区多个数据页,数量大于56,就会把下一个相邻数据区全部数据页加载进bufferpool。这种情况,就让bufferpool里一下子多了很多可能不会被用到的数据页。

比如,某些SQL触发了全表扫描,bufferpool就被迫加载了全表数据到bufferpool,bufferpool可用空闲数据页很快就会被占满,淘汰数据页的考虑就迫在眉睫。

3.4.2 传统LRU链表

如果按普通LRU最近最少使用链表设计,当bufferpool加载一个数据页进来时,LRU链表就会把该数据页描述信息放置到LRU链表头部节点,后续如果查询命中、或者修改了该数据页,该数据页描述信息也会被挪到LRU链表头部。这样LRU链表的尾部节点,一定是最近最少被使用的节点。淘汰数据页就从LRU尾部进行淘汰。

但是刚才InnoDB 预读机制来看,传统简单的LUR链表,之前被频繁访问修改的数据页,很可能被预加载进来的其他没有价值的数据页一下子排挤到LRU链表的尾部。比如数据页C本来是LRU链表头部节点,最近1min被访问了100次,但是由于最近一次全表扫描、或者触发了线性预读,下一个数据区的不需要的数据页B等多个数据页被加载进来,数据页C直接被LRU挪到尾部,面临被淘汰的风险。这个传统简单LRU设计,在预读机制影响下,并不合理公平,需要改进。

3.4.3 改进型LRU链表-1分为2冷热分离设计

bufferpool的LRU链表是经过优化改进的链表,它的设计和优化思路值得参考学习。具体是:LRU链表,一分为二,有热数据区+冷数据区组成链表。

冷热数据占比情况,通过参数innodb_old_blocks_pct配置,默认冷数据占比37%,热数据63%,大概是46开占比。

当数据页首次被加载到bufferpool后,不是直接放到LRU链表头部,而是放在LRU链路冷数据区部分的头部。

此外,数据页描述信息节点进入冷数据区头部后,需要经过innodb_old_blocks_time(默认是1000ms)后,也就是1s后,如果有被再次访问,才能被挪到热数据区的头部,也就是整个LRU链表的头部。

这个LRU链表冷热分离,以及数据页从冷数据到成为真正热数据的规则的设计,可以有效避免预读机制对LRU淘汰公平性破坏。

最后,MySQL在热数据区里也继续做了优化,在LRU热数据区只有后75%的数据页被访问了,才会挪到热数据区头部。前面25%被访问的数据页不会再次修改LRU链表,这样可以有效避免LRU链表因为那些top级火热的数据,频繁访问引起LRU节点变化影响性能。


3.5 缓存数据页刷盘机制

当bufferpool存满后,free链表没有可用空闲数据页,必须要刷盘。当然也不是一定要等到bufferpool没有可用数据页空间才刷盘。MySQL有个定时线程专门负责将LRU链表尾部冷数据以及flush链表脏数据刷盘。该线程会定时把lru链表尾部未被修改的数据直接释放掉,给free链表增加可用数据页。也会从flush链表找那些已经被修改过的脏数据页刷到磁盘,然后增加到free链表。

这里有个参数innodb_lru_scan_depth,用来设置LRU列表中可用页的数量,默认是1024。当lru可用数据页节点数量小于1024时,会发生checkpoint,需要移除LRU列表冷数据区部分数据页。

综上,bufferpool核心运行原理大致如下:当bufferpool加载一个数据页后,free链表移除该数据页描述信息节点,而lru链表会在冷数据区头部新增该数据页描述信息节点。当该数据页被修改后,flush链表会新增该数据页描述信息节点,此外lru链表会把该数据页从冷数据区移动到热数据区,或者在热数据区后75%的位置挪到lru热数据区头部位置。当触发刷盘策略后,lru链表的冷数据或者flush表对应的脏数据页,会被优先刷盘或者从对应链表移除释放,提供新的free可用数据页节点。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
16天前
|
自然语言处理 搜索推荐 关系型数据库
MySQL实现文档全文搜索,分词匹配多段落重排展示,知识库搜索原理分享
本文介绍了在文档管理系统中实现高效全文搜索的方案。为解决原有ES搜索引擎私有化部署复杂、运维成本高的问题,我们转而使用MySQL实现搜索功能。通过对用户输入预处理、数据库模糊匹配、结果分段与关键字标红等步骤,实现了精准且高效的搜索效果。目前方案适用于中小企业,未来将根据需求优化并可能重新引入专业搜索引擎以提升性能。
|
6天前
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
32 16
|
1月前
|
关系型数据库 MySQL 数据库
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
随着数据量增长和业务扩展,单个数据库难以满足需求,需调整为集群模式以实现负载均衡和读写分离。MySQL主从复制是常见的高可用架构,通过binlog日志同步数据,确保主从数据一致性。本文详细介绍MySQL主从复制原理及配置步骤,包括一主二从集群的搭建过程,帮助读者实现稳定可靠的数据库高可用架构。
88 9
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
|
5天前
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
19 4
|
1月前
|
存储 关系型数据库 MySQL
MySQL底层概述—6.索引原理
本文详细回顾了:索引原理、二叉查找树、平衡二叉树(AVL树)、红黑树、B-Tree、B+Tree、Hash索引、聚簇索引与非聚簇索引。
MySQL底层概述—6.索引原理
|
1月前
|
SQL 监控 关系型数据库
MySQL原理简介—12.MySQL主从同步
本文介绍了四种为MySQL搭建主从复制架构的方法:异步复制、半同步复制、GTID复制和并行复制。异步复制通过配置主库和从库实现简单的主从架构,但存在数据丢失风险;半同步复制确保日志复制到从库后再提交事务,提高了数据安全性;GTID复制简化了配置过程,增强了复制的可靠性和管理性;并行复制通过多线程技术降低主从同步延迟,保证数据一致性。此外,还讨论了如何使用工具监控主从延迟及应对策略,如强制读主库以确保即时读取最新数据。
MySQL原理简介—12.MySQL主从同步
|
26天前
|
缓存 关系型数据库 MySQL
图解MySQL【日志】——Buffer Pool
Buffer Pool 是数据库管理系统(DBMS)中用于缓存磁盘数据页的内存区域,主要包含数据页、索引页、undo 页等。它通过减少磁盘 I/O 提升性能,特别是在处理大型数据库时效果显著。查询时,整个数据页而非单条记录会被加载到 Buffer Pool 中,以提高访问效率。
22 0
图解MySQL【日志】——Buffer Pool
|
1月前
|
SQL 关系型数据库 MySQL
MySQL原理简介—11.优化案例介绍
本文介绍了四个SQL性能优化案例,涵盖不同场景下的问题分析与解决方案: 1. 禁止或改写SQL避免自动半连接优化。 2. 指定索引避免按聚簇索引全表扫描大表。 3. 按聚簇索引扫描小表减少回表次数。 4. 避免产生长事务长时间执行。
|
1月前
|
SQL 存储 关系型数据库
MySQL原理简介—10.SQL语句和执行计划
本文介绍了MySQL执行计划的相关概念及其优化方法。首先解释了什么是执行计划,它是SQL语句在查询时如何检索、筛选和排序数据的过程。接着详细描述了执行计划中常见的访问类型,如const、ref、range、index和all等,并分析了它们的性能特点。文中还探讨了多表关联查询的原理及优化策略,包括驱动表和被驱动表的选择。此外,文章讨论了全表扫描和索引的成本计算方法,以及MySQL如何通过成本估算选择最优执行计划。最后,介绍了explain命令的各个参数含义,帮助理解查询优化器的工作机制。通过这些内容,读者可以更好地理解和优化SQL查询性能。
|
2月前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决

相关产品

  • 云数据库 RDS MySQL 版