Buffer Pool缓存页不够时,如何淘汰缓存?

Buffer Pool缓存页不够时,如何淘汰缓存?

若BP缓存页不够了,咋办?

执行CRUD都会将磁盘数据页加载到缓存页,那在加载数据到缓存页时,必然是要加载到空闲缓存页,所以必须要从free中找个空闲缓存页,然后把磁盘数据页加载到该空闲缓存页

image

随着不断将磁盘数据页加载到空闲缓存页,free中的空闲缓存页会越来越少。最终耗尽free中的空闲缓存页。这时,还要加载数据页到一个空闲缓存页时,MySQL 该何去何从?

若所有缓存页都有数据了,那就无法再从磁盘加载新数据页到缓存页了,则只能淘汰一些缓存页:把一个缓存页里被修改过的数据,刷到磁盘的数据页,然后该缓存页就能被清空, 变回空闲页。然后就能将磁盘的新数据页加载到这刚腾出的空闲页:

那应该把哪个倒霉的缓存页的数据刷盘呢?

缓存命中率

现有两个缓存页:

  • 一个缓存页的数据,经常被修改和查询,都可以操作缓存,不需要从磁盘加载数据,这那缓存命中率就很高。这种高级员工就是啥脏活累活,都会接受。
  • 另一个缓存页里的数据,刚从磁盘加载到缓存页后,被修改和查询过1次,之后100次请求再没有一次是修改和查询该缓存页数据的,那这缓存命中率就有点低了,因为大部分请求还是走磁盘查询数据,他们要操作的数据不在缓存。这种高级员工啥事都干不了,都还得交给低级员工们干事。

很显然,作为领导的你,肯定想把第二个员工裁了吧?

引入LRU,判断哪些缓存页不常用

如何知晓哪些缓存页经常被访问,哪些缓存页很少被访问?

这就需要LRU,Least Recently Used,最近最少使用。这样当缓存页需空出一个刷盘时,通过LRU链表,就能知道最近最少被使用的缓存页。

LRU工作原理

假设从磁盘加载一个数据页到缓存页时,就将该缓存页的描述信息块放入LRU链表头部,那么只要有数据的缓存页,他都会在LRU里,最近被加载数据的缓存页,都会放到LRU链表头部。

假设某缓存页的描述信息块本在LRU链尾,后续你只要查询或修改了该缓存页数据,也要将这缓存页移到LRU链头,即最近被访问过的缓存页,一定在LRU链头

如此,当无空闲缓存页时候,就能轻易找出最近最少被访问的缓存页去刷盘,即LRU链尾的缓存页,将其刷盘,然后把你需要的磁盘数据页加载到这刚空出的缓存页。

表和行等概念和表空间、数据页的关系

  • 表、列和行,都是逻辑概念,我们只关注DB里有一个表,表里有几个字段,有多少行,但是这些表里的数据
  • 表空间、数据页等是物理概念,在物理层面,表里的数据都放在一个表空间,表空间由一堆磁盘上的数据文件组成,这些数据文件里都存放了表中的数据,这些数据由一个个数据页组织起来

但这样的LRU实际运行时会有问题。

预读

当你从磁盘加载一个数据页时,他可 能会连带着把该数据页相邻的其他数据页,也加载到缓存。

现有两个空闲缓存页,加载一个数据页时,连带着把他的一个相邻数据页也加载到缓存,正好每个数据页放入一个空闲缓存页!

然后呢?实际上只有一个缓存页被访问,另外一个通过预读机制加载的缓存页,其实无人问津,此时这俩缓存页可都在LRU链表前边:

image

这时,若无空闲页了,要加载新数据页,就得从LRU链表的尾部将“最近最少使用的缓存页”取出,刷入磁盘,就空出一个缓存页了。

若选择将上图中LRU尾部那个缓存页刷盘,然后清空,合理吗?

他可是之前一直频繁被访问呀,只是这一瞬间,被新加载进的两个缓存页给占了LRU链表前面的位置,尤是第二个缓存页,居然还是通过预读加载来的,其实根本无人访问!而这时将LRU链表尾部缓存页刷盘,肯定不合理,最合理的反而是将那LRU链表第二个通过预读机制加载进的缓存页给淘汰。

MySQL预读触发时机

  1. 参数innodb_read_ahead_threshold默认56,即若顺序访问了一个区里的多个数据页,访问的数据页数量超过阈值,就会触发预读,将下个相邻区中的所有数据页都加载到缓 存

  2. 若BP里缓存了一个区里的13个连续的数据页,而且这些数据页都是比较频繁会被访问的,此时直接触发预读,把这个区里的其他的数据页都加载到缓存里去。该机制通过参数innodb_random_read_ahead控制,默认OFF关闭。

所以默认主要第一个规则可能触发预读,一下将很多相邻区里的数据页加载进缓存,这些缓存页若突然都放在LRU链表前面,且他们其实并没啥人访问,就会如上图,导致本就在缓存里的一些频繁被访问的缓存页却在LRU链尾。后续一旦要淘汰缓存页,就会将链尾的一些频繁被访问的缓存页给淘汰!

全表扫描

如:

SELECT * FROM xxx

一下子就将表里所有数据页都从磁盘加载到BP。这时他可能会一下子就把这个表的所有数据页都装入各缓存页。此时可能LRU链表中排在前面的一大串缓存页,都是全表扫描加载进来的。若此次全表扫描后,后续几乎没用到这个表里的数据呢?此时LRU链尾可能全都是之前一直被频繁访问的那些缓存页!

然后当需要淘汰缓存页时,就会将LRU链表尾部一直被频繁访问的缓存页给淘汰掉了,而留下之前全表扫描加载进来的大量的不经常访问的缓存页。

为何MySQL设计预读机制,为何有时要把相邻的一些数据页一次性读入到Buffer Pool缓存?

为提升性能。假设你读取了数据页01到缓存页里去,那接下来有可能会接着顺序读取数据页01相邻的数据页02到缓存页,是不是可能在读取数据页02的时候要再次发起一次磁盘IO?

所以为优化性能,MySQL设计了预读机制,即若在一个区内,你顺序读取了好多数据页,比如数据页01~56都被你依次顺序读取了,MySQL觉得你可能接着会继续顺序读取后面的数据页。

此时他干脆提前把后续一大堆数据页(如数据页57~72)都读取到Buffer Pool,后续你再读取数据页60时,就能直接从Buffer Pool里拿到。

但现实骨感,预读的一大堆数据页要是占据LRU链表前面部分,然而可能这些预读的数据页压根儿后续无人用,那这预读机制对性能不增反减。

冷热分离的LRU

于是,为了解决前面的问题,真正MySQL采取冷热数据分离思想改良了 LRU。

之前问题都是因为所有缓存页都混在一个LRU链表才导致的,改良版LRU链表拆为热数据、冷数据两部分,冷热数据比例由innodb_old_blocks_pct参数控制,默认37,即冷数据占37%。这时的LRU链表:

image

数据页第一次被加载到缓存时,缓存页会被放在冷区的链表头部。

冷区缓存页何时放入热区?

第一次被加载了数据的缓存页都会不停移动到冷区的链表头部。那为何不放到热区头部呢?

你刚加载了一个数据页到那个缓存页,他在冷区的链表头部,然后立马(在1ms以内)就又被访问了,但之后就再也不访问了呢?难道这种情况也要把这缓存页放到热区头部吗?

所以MySQL设innodb_old_blocks_time参数,默认1000,即1000ms:一个数据页被加载到缓存页之后,在1s后,你又访问了该缓存页,他才会被移到热区的链表头部。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容