MySQL有一个最大的缓冲区  Buffer  Pool(默认大小128M),用来缓存  页 ,将查询到的页放到  Buffer  Pool

    这时有一个  free链表,头节点存储了当前链表的元素个数以及下一个链表在哪里,后续的链表存储 Buffer  Pool里哪些区域是空闲的,当空闲的Buffer  Pool的区域被使用的时候,相应的free链表的节点也被删除

    同时又有一个  lru链表,头节点也是存储了当前链表的元素个数,来将在free链表中删除的节点加入到  lru链表中的头节点后面,使用最近最少使用算法,最近被使用节点也会放到头节点后面,

    当再一次更新中,Buffer  Pool 中所有的数据全部换掉, 这一行为被称作换血

    为了避免换血这种情况发生,MySQL对   lru  链表进行了升级,前 5/8 的部分用来存储热数据,也就是经常访问的数据,后 3/8 的部分用来存储冷数据,也就是不是经常被访问的数据,而且冷数据也可以升级成为热数据,当一个冷数据被连续访问,而且两次访问时间相差大于1s,t2   -   t1  >  1s,避免一个SQL语句连续访问多次冷数据,这时候这页冷数据就升级成为了热数据,同时最后一条热数据被淘汰掉成为冷数据。

    前   1/4  的热数据没有必要交换,也就是没必要看谁是最长被访问的数据,因为会造成前面的热数据进行多次没有意义的交换,本质是:这是淘汰的机制,而不是找出最热的机制,没有必要浪费时间

 

    Buffer  Pool里面肯定有一些页是被修改的,我们称之为脏页,MySQL内置了线程  定时地更新脏页

    类似free链表,当Buffer  Pool中有页被update 更新修改之后,会放在  flush链表头节点后面,之后内置定时更新地线程 会在链表里面找相应的地址来进行更新

 

                                                     

    对于更新脏页,MySQL有两个 Redo Log日志,专门来存储脏页相关地日志,当两个日志全都存储满了之后或者后台线程定时地   就开始更新脏页进行持久化,这就完成了从随机IO到顺序IO地转变

    但是,有可能在进行事务的时候两个日志满了必须进行持久化,就会让事务滞后,这时我们可以进行对Read Log 的配置,让空间变大或者数量变多。但是同样有弊端,当MySQL因为一些原因挂掉的话,需要依靠  Read Log 日志进行数据的恢复,就回导致打开MySQL的速度变慢

 

    双写缓冲区————脏页有16kb,但是操作系统每次写只能写入4kb,所以要分4次写入磁盘进行持久化,但是有可能写入了1、2、3次而中途挂掉,最终导致没有一次性写完

    在磁盘里面开辟一个新的空间,让Buffer  Pool中脏页的数据进行持久化写入到这个新开辟的空间中,如果写入成功,就根据这个新数据再写入磁盘中原有的老数据,如果这时候程序挂掉,可以再根据新数据对比老数据进行继续持久化写入,如果没挂掉就成功了。如果在第一次写入的到新开辟的空间的时候中途挂掉,老数据区域可以根据Redo Log 进行持久化写入。

    但是现在有一些的硬盘是支持源自写入的,意味着要么将16kb的数据全部写完,要么16kb数据全部都不写入。

 

    

 

              双写缓冲区示意图

 

 

 

posted on 2022-03-17 21:13  迎新  阅读(153)  评论(0编辑  收藏  举报