相信大家对LRU链表是不陌生的,算是一种基础的数据结构!

LRU:Least Recently Used

一、简述传统的LRU链表

LRU:Least Recently Used

相信大家对LRU链表是不陌生的,它算是一种基础的数据结构吧,而且想必面试时也被问到过什么是LRU链表,甚至是让你手写一个LRU链表。

如果你读了上一篇:你有没有搞混查询缓存和BufferPool?谈谈看!

想必你已经知道了MySQL的Buffer Pool机制以及MySQL组织数据的最小单位是数据页。并且你也知道了 数据页在Buffer Pool中是以LRU链表的数据结构组织在一起的。

其实所谓的LRU链表本质上就是一个双向循环链表,如下图:

下面我们结合LRU链表和数据页机制描述一下MySQL加载数据的机制:

我们将从磁盘中读取的数据页称为young page,young page会被直接放在链表的头部。已经存在于LRU链表中数据页如果被使用到了,那么该数据页也被认为是young page而被移动到链表头部。这样链表尾部的数据就是最近最少使用的数据了,当Buffer Pool容量不足,或者后台线程主动刷新数据页时,就会优先刷新链表尾部的数据页。

二、传统LRU链表的不足

相信你之前肯定听说过操作系统级别的空间局部性原理:

spatial locality(空间局部性):也就是说读取一个数据,在它周围内存地址存储的数据也很有可能被读取到,于是操作系统会帮你预读一部分数据。

MySQL也是存在存在预读机制的!

  1. 当Buffer Pool中存储着一个区中13个连续的数据页时,你再去这个区里面读取,MySQL就会将这个区里面所有的数据页都加载进Buffer Pool中的LRU链表中。(然后可能你根本不会使用这些被预读的数据页)
  2. 当你顺序的访问了一个区中大于 innndb_read_ahead_threshold=56个数据页时,MySQL会自动帮你将下一个相邻区中的数据页读入LRU链表中。(这个机制默认是被关闭的)
  3. 当你执行select * from xxx;时,如果表中的数据页非常多,那这些数据页就会一一将Buffer Pool中的经常使用的缓存页挤下去,可能留在LRU链表中的全部是你不经常使用的数据。

综上你可以看到,所谓的预读机制的优势,实际上违背了LRU去实现将最近最少使用的数据页刷入磁盘的设计初衷。

三、MySQL的LRU链表

接下来我们看下MySQL的Buffer Pool是如何定制LRU链表的,已经LRU帮InnoDB解决了什么问题。

当业务进行大量的CRUD时,需要不断的将数据页读取到buffer pool中的LRU链表中。

MySQL的LRU链表长下面这样。

LRU链表被MidPoint分成了New Sublist和Old Sublist两部分。

其中New Sublist大概占比5/8,Old Sublist占比3/8。

New Sublist存储着young page,而Old Sublist存储着Old Page。

我们可以通过如下的方式查看MidPoint的默认值。

用户可以根据自己的业务动态的调整这个参数!

这其实是一种冷热数据分离设计思想。他相对于传统的LRU链表有很大的优势

四、MySQL定制LRU链表的优势

而对于MySQLLRU链表来说,通过MidPoint将链表分成两部分。

从磁盘中新读出的数据会放在Old Sublist的头部。这样即使你真的使用select * from t;也不会导致New Sublist中的经常被访问的数据页被刷入磁盘中。

正常情况下,访问Old Sublist中的缓存页,那么该缓存页会被提升到New Sublist中成为热数据。

但是当你通过 select * from t 将一大批数据加载到Old Sublist时,然后在不到1s内你又访问了它,那在这段时间内被访问的缓存页并不会被提升为热数据。 这个1s由参数innodb_old_blocks_time控制。

另外:New SubList也是经过优化的,如果你访问的是New SubList的前1/4的数据,他是不会被移动到LRU链表头部去的。

当然你可能对什么是数据区并不了解,别急。白日梦将在第13篇文章中同你分享什么是数据区

五、推荐阅读

1、谈谈MySQL中基数是什么?

2、聊聊什么是慢查?如何监控?如何排查?

3、对Not Null字段插入Null值有啥现象?

4、能谈谈year、date、datetime、time、timestamp的区别吗?

5、你有没有搞混查询缓存和Buffer Pool?谈谈看!

参考:

https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool.html

https://dev.mysql.com/doc/refman/5.7/en/innodb-performance-midpoint_insertion.html

https://dev.mysql.com/doc/refman/5.7/en/innodb-performance-read_ahead.html

关注送书!《Netty实战》



文章公号号首发!连载中!关注微信公号回复:“抽奖” 可参加抽活动

你知道MySQL的LRU链表吗?的更多相关文章

  1. linux内存源码分析 - 内存回收(lru链表)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 对于整个内存回收来说,lru链表是关键中的关键,实际上整个内存回收,做的事情就是处理lru链表的收缩,所以 ...

  2. (转)linux内存源码分析 - 内存回收(lru链表)

    原文:http://www.cnblogs.com/tolimit/p/5447448.html 概述 对于整个内存回收来说,lru链表是关键中的关键,实际上整个内存回收,做的事情就是处理lru链表的 ...

  3. mysql 原理 ~ LRU 算法与buffer_pool

    一 简介:针对查询和事务的页在内存中的处理,是如何进行的 二 LRU算法 普通 : 实现的是末尾淘汰法,当整个链表已满时,淘汰尾部,将新的数据页加入头部 mysql_lru改进 : 分为两部分 yan ...

  4. mysql执行拉链表操作

    拉链表需求: 1.数据量比较大 2.变化的比例和频率比较小,例如客户的住址信息,联系方式等,比如有1千万的用户数据,每天全量存储会存储很多不变的信息,对存储也是浪费,因此可以使用拉链表的算法来节省存储 ...

  5. 用十一张图讲清楚,当你CRUD时BufferPool中发生了什么!以及BufferPool的优化!

    一.收到了大佬们的建议 1.篇幅偏短,建议稍微加长一点. 这点说的确实挺对,有的篇幅确实比较短,针对这个提议我会考虑将相似的话题放在一篇文章中.但是这可能会导致我中断每天更新的步调,换成隔几天发一篇的 ...

  6. InnoDB学习(一)之BufferPool

    我们知道InnoDB数据库的数据是持久化在磁盘上的,而磁盘的IO速度很慢,如果每次数据库访问都直接访问磁盘,显然严重影响数据库的性能.为了提升数据库的访问性能,InnoDB为数据库的数据增加了内存缓存 ...

  7. MySQL内核:InnoDB存储引擎 卷1

    MySQL内核:InnoDB存储引擎卷1(MySQL领域Oracle ACE专家力作,众多MySQL Oracle ACE力捧,深入MySQL数据库内核源码分析,InnoDB内核开发与优化必备宝典) ...

  8. 快速入门系列--MySQL

    一直说要好好复习一下Mysql都木有时间,终于赶上最近新购买了阿里云,决定使用CentOS去试试.NET Core等相关的开发,于是决定好好的回顾下这部分知识,由于Mysql的数据库引擎是插件式的,对 ...

  9. MySQL表定义缓存

    表定义 MySQL的表包含表名,表空间.索引.列.约束等信息,这些表的元数据我们暂且称为表定义信息. 对于InnoDB来说,MySQL在server层和engine层都有表定义信息.server层的表 ...

随机推荐

  1. Pycharm开发环境配置与调试

    在Windows宿主机上搭建Ubuntu虚拟机的Pycharm开发环境,Ubuntu开启Samba服务,使用网络映射将Ununtu下Python项目工程路径映射到Windows下 创建Pycharm工 ...

  2. 1T数据快速排序!十种经典排序算法总结

    1 冒泡排序 每次循环都比较前后两个元素的大小,如果前者大于后者,则将两者进行交换.这样做会将每次循环中最大的元素替换到末尾,逐渐形成有序集合.将每次循环中的最大元素逐渐由队首转移到队尾的过程形似&q ...

  3. 扫描仪扫描文件处理-A4分辨率

    转换公式:毫米转英寸,英寸乘以DPI(每英寸点数) 1英寸 = 2.54 厘米 = 25.4 毫米 例子(600dpi):mm: 210x297 = px: 4961(210/25.4*600)x70 ...

  4. spring boot:用spring security加强druid的安全(druid 1.1.22 / spring boot 2.3.3)

    一,druid的安全保障有哪些环节要注意? 1,druid ui的访问要有ip地址限制 2,用户必须要有相应的权限才能访问druid 3,关闭重置功能 说明:stat-view-servlet.url ...

  5. Centos7 安装python环境

    保留python2 找到python所在位置,把python指向python2.7备份 [root@sun /usr/bin]# cd ~ [root@sun ~]# whereis python p ...

  6. MySql中varchar和char,如何选择合适的数据类型?

    背景 学过MySQL的同学都知道MySQL中varchar和char是两种最主要的字符串类型,varchar是变长的类型,而char是固定长度.那关于如何选择类型就成为令人头疼的事,很多初学者为了保证 ...

  7. docker 启动mysql 挂载宿主机目录

    在使用docker run 运行镜像获取容器时,有些容器会自动产生一些数据,为了这些数据会因为container (容器)的消失而消失,保证数据的安全,比如mysql 容器在运行中产生的一些表的数据, ...

  8. 常见的Python运行时错误

    date: 2020-04-01 14:25:00 updated: 2020-04-01 14:25:00 常见的Python运行时错误 摘自 菜鸟学Python 公众号 1. SyntaxErro ...

  9. CTF:sctf_2019_easy_heap

    这个题目当时比赛的时候靶机据说是ubuntu16.04,但是迁移到buu上就变成了ubuntu18.04,下面针对两个平台给出不同的解法,先写一下18.04下的 先来逆一下,关键点有一下几个 mmap ...

  10. Redis基础(二)数据库

    数据库 Redis服务器的所有数据库都保存在redisServer.db数组中,而数据库的数量则由redisServer.dbnum属性保存. struct redisServer { // .. / ...