MySQL高手第三章
从磁盘读取数据页到Buffer Pool的时候free链表有什么用我们怎么知道那些缓存是空闲的当我们数据库运行起来的时候肯定会不断的做增删改查将磁盘上读取一个一个数据页放入Buffer Pool中对应的缓存页里去但是从磁盘数据页放入Buffer Pool中的缓存页的时候必然涉及到一个问题那些缓存页是空闲的数据库会设计一个free链表一个双向链表这个free链表里每个节点就是一个空闲的缓存页描述数据块的地址只要你一个缓存页是空闲的那么他的描述数据块就会放入这个free链表中free链表中占用了多少内存空间这个free链表他本身就是由Buffer Pool里的描述数据块组成的可以认为是每个描述数据块里都有两个指针一个是free_pre一个是free_next对于free链表而言只有一个基础节点是不属于Buffer Pool的他是40字节大小的一个节点里面存放着链表头节点的地址尾节点的地址还有free链表里当前有多少个节点如何将磁盘上的页读取到Buffer Pool缓存页中去只要将free链表里获取一个描述数据块然后就可以对应的获取足够描述数据块对应的空闲缓存页怎么知道数据页有没有被缓存数据库有一个哈希表数据结构他会用表空间号数据页号作为一个key然后缓存页的地址作为value当你使用一个数据页的时候通过表空间号数据页号作为这个key去这个哈希表里检查一下如果没有就读取数据页如果有就代表存在当我们更新Buffer Pool数据时flush链表有什么用脏数据页为什么脏我们要更新的数据页都会在Buffer Pool的缓存页里共我们在内存执行增删改操作接下来去更新Buffer Pool缓存页中的数据此时一旦更新了缓存页中的数据那么缓存页里的数据和磁盘上的数据页里的数据就会不一致这个就叫做脏数据脏页哪些缓存页是脏页我们之前学过最终在内存里更新的脏页的数据都是要被刷新回磁盘文件的但是不可能所有缓存页都刷回磁盘的因为有的缓存页可能因为查询的时候被读取到Buffer Pool里去可能没有被修改所有数据库在这里需要引入和free表类似的flush链表其本质就是通过缓存页的数据块中的两个指针让被修改的缓存页的数据块组成一个双向链表凡是被修改的缓存页都会把他的描述数据块加入到flush链表中flush意思是脏数据后续都要刷新flush到磁盘当Buffer Pool的缓冲页不够的时候如何基于LRU算法淘汰部分内存当我们执行CRUD的时候无论是查询数据还是修改数据实际上都会把磁盘的数据页加载到缓存页里来。那么在加载数据到缓存页的时候必然是要加载到空闲的缓存页中所有必须要从free链表中找一个空闲的缓存页然后把磁盘上的缓存页加载到那个空闲的缓存页里去。随着不停把磁盘上的数据页加载到空闲的缓存页中free链表中的空闲缓存页会越来越少迟早有一刻缓存页会满这时候还要加载一个空闲的缓存页该怎么办针对这个问题我们就需要使用淘汰缓存页了缓存命中率概念引入假设现在有两个缓存页一个缓存页的数据经常被修改和查询比如命中100次请求有30次请求都在查询和修改这个缓存页中的数据这样就是这个缓存命中率高另外一个查询和修改在100次请求中就命中1个那么其命中率就很低现在如果我们要腾出空间来选择一个我们肯定会选择第二种方式LRU算法我们怎么知道哪些缓存经常被访问哪些缓存很少被访问这时候就需要LRU链表也就是最近最少使用的意思简单的LRU算法会遇到哪些问题预读机制首先会带来隐患的是MySQL的预读机制当你从磁盘上加载一个数据页的时候他可能会连带着把这个数据页相邻的其他数据页也加载到缓存当中哪些情况下会触发MySQL的预读机制有一个参数innodb_read_ahead_threshold默认是56如果顺序访问一个区里的多个数据页访问的数据页的数量超过了这个阈值此时就会触发预读机制把下一个相邻区域中的所有数据页都加载到缓存里面去如果Buffer Pool里缓存了一个区里的13个连续的数据页而且这些数据页都是比较频繁被访问的此时就会发送预读机制把这个区域中的数据加到缓存中这个机制是由innodb_random_read_ahead来控制的默认是OFF也就是关闭的意思另外一种可能导致频繁被访问的缓存页被淘汰的场景全表扫描会导致一下子将这个表所有的数据页都从磁盘加载到Buffer Pool里面去这时候会导致以前经常访问的缓存页都被淘汰了MySQL是如何基于冷热数据分离方案来优化LRU算法的冷热数据分离前面我们说明了简单的LRU算法带来的问题而MySQL肯定也考虑到了这一点所以他们使用的是冷热数据分离的思想真正的LRU链表是拆分为两部分一部分是热数据一部分是冷数据这个比例是由innodb_old_blocks_pct参数控制的默认是37%也就是冷数据占37%运行流程第一次加载一个缓存页的时候其会先放到冷数据链表的头部MySQL里面设定了一个参数innodb_old_blocks_time默认为1000也就是说一个数据页被加载到缓存页后1s之后访问这个缓存页他才会被挪动到热数据链表的头部解决之前的问题前面我们说到全部扫描这时候不就迎刃而解当全表扫描的时候会将其全部放到冷数据头部的位置而不影响热数据
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2455268.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!