但是这样子还不是足够完美,为什么这么说,刚刚我们一直在讨论的是冷数据区的数据被访问,然后在一定规则之下会被加载到热数据链表的头部,但是现在某个请求需要访问的数据就在热数据区,那是不是直接把该数据所在的缓存页对应的描述数据转移到热数据区链表头部呢?
很显然不是这样子的,因为热数据区的数据本身就是会被频繁访问的,这样子如果每次访问都去移动链表,势必造成性能的下降(影响再小极端情况下也可能会不可控),所以 MySQL针对热数据区的数据的转移也有相关的规则 。
该规则就是:如果被访问的数据所在的缓存页在热数据区的前25%,那么该缓存页对应的描述数据是不会被转移到热数据链表的头部的,只有当被访问的缓存页对应的描述数据在热数据区链表的后75%,该缓存页的描述数据才会被转移到热数据链表的头部 。
举个例子来说,假设热数据区有100个缓存页(这里的缓存页还是指的是缓存页对应的描述数据,再强调下,链表中存放的是缓存页的描述数据,为了方便有时候会直接说缓存页 。希望朋友们注意),当被访问的缓存页在前25个的时候,热数据区的链表是不会有变化的,当被访问的缓存页在26~100(也就是数据在热数据区链表的后75%里面)的时候,这个时候被访问的缓存页才会被转移到链表的头部 。
到此为止,MySQL对于LUR 链表的优化就堪称完美了 。是不是看到这里瞬间感觉很多东西都明朗了,好了,对于 LRU 链表我们就讨论到这里了 。
10、Buffer Pool 中的链表小结# free链表用来存放空闲的缓存页的描述数据,如果某个缓存页被使用了,那么该缓存页对应的描述数据就会被从free链表中移除# flush链表被修改的脏数据都记录在 Flush 中,同时会有一个后台线程会不定时的将 Flush 中记录的描述数据对应的缓存页刷新到磁盘中,如果某个缓存页被刷新到磁盘中了,那么该缓存页对应的描述数据会从 Flush 中移除,同时也会从LRU链表中移除(因为该数据已经不在 Buffer Pool 中了,已经被刷入到磁盘,所以就也没必要记录在 LRU 链表中了),同时还会将该缓存页的描述数据添加到free链表中,因为该缓存页变得空闲了 。# LRU链表数据页被加载到 Buffer Pool 中的对应的缓存页后,同时会将缓存页对应的描述数据放到 LRU 链表的冷数据的头部,当在一定时间过后,冷数据区的数据被再次访问了,就会将其转移到热数据区链表的头部,如果被访问的数据就在热数据区,那么如果是在前25%就不会移动,如果在后75%仍然会将其转移到热数据区链表的头部后台线程将冷数据区的尾节点的描述数据对应的缓存页刷入磁盘文件中

文章插图
11、Buffer Pool 的并发性能我们平时的系统绝对不可能每次只有一个请求来访问的,说白了就是如果多个请求同时来执行增删改,那他们会并行的去操作 Buffer Pool 中的各种链表吗?如果是并行的会不会有什么问题 。
实际上 MySQL在处理这个问题的时候考虑的非常简单,就是: Buffer Pool 一次只能允许一个线程来操作,一次只有一个线程来执行这一系列的操作,因为MySQL 为了保证数据的一致性,操作的时候必须缓存池加锁,一次只能有一个线程获取到锁 。
这个时候,大家这时候肯定满脑子问号 。串行那还谈什么效率?大家别忘记了,这一系列的操作都是在内存中操作的,实际上这是一个瞬时的过程,在内存中的操作基本是几毫秒的甚至微妙级别的事情 。
但是话又说回来,串行执行再怎么快也是串行,虽然不是性能瓶颈,这还有更好的优化办法吗?那肯定的 MySQL早就设计好了这些规则 。那就是 Buffer Pool 是可以有多个的,可以通过 MySQL的配置文件来配置,参数分别是:
#Buffer Pool的总大小innodb_buffer_pool_size=8589934592#Buffer Pool的实例数(个数)innodb_buffer_pool_instance=4一般在生产环境中,在硬件不紧张的情况下,建议使用此策略 。这个时候大家是不是又会有一个疑问(如果没有那说明你没认真思考哦),大家应该有这样的疑问:# 问:多个 Buffer Pool 所带来的问题思考在多个线程访问不同的 Buffer Pool 那不同的线程加载的数据必然是在不同的 Buffer Pool 中,假设 A 线程加载数据页A到 Buffer Pool A 中,B 线程加载数据页B到 Buffer PoolB 中,然后两个都执行完了,这个时候 C 线程来了,他到达的是 Buffer Pool B中,但是 C 要访问的数据是在 Buffer Pool A中的数据页上了,这个时候 C 还会去加载数据页A吗?,这种情况会发生吗?在不同的 Buffer Pool 缓存中会去缓存相同的数据页吗?# 答:多个 Buffer Pool 所带来的问题解答这种情况很显然不会发生,既然不会发生,那 MySql 是如何解决这种问题的?其实前面已经提到过了,那就是 数据页缓存哈希表(看下图),里面存放的是表空间号+数据页号 = 缓存页地址,所以MySQL 在加载数据所在的数据页的时候根据这一系列的映射关系判断数据页是否被加载,被加载到了那个缓存页中,所以 MySQL 能够精确的确定某个数据页是否被加载,被加载的到了哪个缓存页,绝不可能出现重复加载的情况 。
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 丰臣秀吉手下大将?丰臣秀吉是将军吗
- 乾隆一生最爱的女人是谁?戏说乾隆中乾隆最爱的女人
- 2021年开网店卖什么好?2021年实体店卖什么好_1
- CentOS 静默安装Oracle
- 一次几乎不可能的数据库迁移
- 黑茶熟普洱茶区别,普洱茶生茶熟茶区别
- 嘘,认真看!Layui一定是Java程序员必备后台前端框架
- 考拉功能性灭绝什么意思 考拉为什么没有灭绝
- 深入设计原则-SOLID
- 最丑的外星人 外星生物长什么样子
