| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> MySQL InnoDB内存结构之Buffer Pool -> 正文阅读 |
|
[大数据]MySQL InnoDB内存结构之Buffer Pool |
?https://blog.csdn.net/zwx900102/article/details/106741454 1.什么是buffer pool?? ? ? ? 缓冲池是主内存中的一个区域,InnoDB 在访问时缓存表和索引数据。 缓冲池允许直接从内存中访问经常使用的数据,从而加快处理速度。 在专用服务器上,高达 80% 的物理内存通常分配给缓冲池。为了提高大容量读取操作的效率,缓冲池被划分为可能包含多行的页面。 为了缓存管理的效率,缓冲池被实现为页链表; 很少使用的数据使用最近最少使用 (LRU) 算法的变体从缓存中老化。了解如何利用缓冲池将频繁访问的数据保存在内存中是 MySQL 调优的一个重要方面。 ? ? ? ?咱们在使用mysql的时候,比如很简单的select * from table;这条语句,具体查询数据其实是在存储引擎中实现的,(这里要注意了和缓存不一样,缓存实在Mysql Server层面实现的)大家都知道mysql数据其实是放在磁盘里面的,如果每次查询都直接从磁盘里面查询,这样势必会很影响性能,所以一定是先把数据从磁盘中取出,然后放在内存中,下次查询直接从内存中来取。但是一台机器中往往不是只有mysql一个进程在运行的,很多个进程都需要使用内存,所以mysql中会有一个专门的区域来处理这些数据,这个专门为mysql准备的区域,就叫buffer pool。buffer pool里面采用的是页链表实现的,也就是放在里面的数据都是一页一页的。当首次加载的时候是将从磁盘中取出来的数据放到了空白页面的,被称为Free Page. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?free链表的结构:free链表里面每个节点的控制块指向buffer pool里面的一个Free Page. ? ? ? ?我们在对数据库执行增删改操作的时候,不可能直接更新磁盘上的数据的,因为如果你对磁盘进行随机读写操作,那速度是相当的慢,随便一个大磁盘文件的随机读写操作,可能都要几百毫秒。如果要是那么搞的话,可能你的数据库每秒也就只能处理几百个请求了!?在对数据库执行增删改操作的时候,实际上主要都是针对内存里的Buffer Pool中的数据进行的,对数据库的内也就是实际上主要是存里的数据结构进行了增删改,修改后的页被称为Dirty Page,那么这个脏页是要刷进磁盘的,这时mysql的后台里面会起一个线程,定时的去找这个脏页,然后刷新到磁盘中. 后台线程根据flush List去寻找脏页 ??flush链表的结构: ?当buffer pool缓存池中的数据都装满了,我们就会基于LRU链表进行淘汰 ,用的最多的就会放到最前面? ? 但是直接这样去设计是有问题的昂,有什么问题呢?当然会有问题 ? 预读失效: ?上面我们提到了缓冲池的预读机制可能会预先加载相邻的数据页。假如加载了 20、21 相邻的两个数据页,如果只有页号为 20 的缓存页被访问了,而另一个缓存页却没有被访问。此时两个缓存页都在链表的头部,但是为了加载这两个缓存页却淘汰了末尾的缓存页,而被淘汰的缓存页却是经常被访问的。这种情况就是预读失效,被预先加载进缓冲池的页,并没有被访问到,这种情况是不是很不合理。 缓冲池污染?: ? ? ?还有一种情况是当执行一条 SQL 语句时,如果扫描了大量数据或是进行了全表扫描,此时缓冲池中就会加载大量的数据页,从而将缓冲池中已存在的所有页替换出去,这种情况同样是不合理的。这就是缓冲池污染,并且还会导致 MySQL 性能急剧下降。 基于以上的两种问题: ? ? ? Msyql 基于 LRU 设计了冷热数据分离的处理方案。也就是将 LRU 链表分为两部分,一部分为热数据区域,一部分为冷数据区域。 ? ??当数据页第一次被加载到缓冲池中的时候,先将其放到冷数据区域的链表头部,1s(由 innodb_old_blocks_time 参数控制)?后该缓存页被访问了再将其移至热数据区域的链表头部。 ? ?? ? ? ? ? ?查询 缓冲池的大小:
? 调整缓冲池的大小,调整为2G
2.页链表:三种Page1.1Free Page(空闲页) 表示此Page 未被使用,位于 Free 链表。 1.2. Clean Page(干净页) 此Page 已被使用,但是页面未发生修改,位于LRU 链表。 1.3. Dirty Page(脏页) 此Page 已被使用,页面已经被修改,其数据和磁盘上的数据已经不一致。当脏页上的数据写入磁盘后,内存数据和磁盘数据一致,那么该Page 就变成了干净页。脏页 同时存在于LRU 链表和Flush 链表。 3..redo log? ??其实每个人都担心一个事,就是你在数据库的内存里执行了一堆增删改的操作,内存数据是更新了,但是这个时候如果数据库突然崩溃了,那么内存里更新好的数据不是都没了吗??MySQL就怕这个问题,所以引入了一个redo log机制,你在对内存里的数据进行增删改的时候,他同时会把增删改对应的日志写入redo log中, 万一你的数据库突然崩溃了,没关系,只要从redo log日志文件里读取出来你之前做过哪些增删改操作,瞬间就可以重新把这些增删改操作在你的内存里执行一遍,这就可以恢复出来你之前做过哪些增删改操作了。?当然对于数据更新的过程,他是有一套严密的步骤的,还涉及到undo log、binlog、提交事务、buffer pool脏数据刷回磁盘,等等。 ? ? Buffer Pool就是数据库的一个内存组件,里面缓存了磁盘上的真实数据,然后我们的系统对数据库执行的增删改操作,其实主要就是对这个内存数据结构中的缓存数据执行的。通过这种方式,保证每个更新请求,尽量就是只更新内存,然后往磁盘顺序写日志文件。 更新内存的性能是极高的,然后顺序写磁盘上的日志文件的性能也是比较高的,因为顺序写磁盘文件,他的性能要远高于随机读写磁盘文件。 刷盘是随机 I/O,而记录日志是顺序 I/O,顺序 I/O 效率更高。因此先把修改写入日 志,可以延迟刷盘时机,进而提升系统吞吐? 这是为什么要使用重写日志的原因,并且这个重写日志的空间早就给你开辟好了 默认单个文件是48M. ? 4. update语句的执行流程 上图可以大概概括为以下几步: 上面的步骤中,我们注意到,redo log会经过两次提交,这就是两阶段提交。 两阶段提交 而我们这里redo log是属于存储引擎层的日志,bin log是属于Server层日志,属于两个独立的日志文件,采用两阶段提交就是为了使两个日志文件逻辑上保持一致 5.什么时候redo log会往数据库的磁盘上面刷呢? 默认的值是2 6.bin log 可能有人会问,为什么会有两份日志呢? bin log和redo log的区别 来源: |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/16 3:44:35- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |