专栏名称: 芋道源码
纯 Java 源码分享公众号,目前有「Dubbo」「SpringCloud」「Java 并发」「RocketMQ」「Sharding-JDBC」「MyCAT」「Elastic-Job」「SkyWalking」「Spring」等等
目录
相关文章推荐
芋道源码  ·  Spring Cloud Gateway ... ·  16 小时前  
芋道源码  ·  Spring Boot + URule ... ·  16 小时前  
芋道源码  ·  入职第一天,看了公司代码,牛马沉默了 ·  昨天  
Java编程精选  ·  Controller层代码这么写,简洁又优雅! ·  2 天前  
51好读  ›  专栏  ›  芋道源码

一网打尽总结 Mysql 的所有 Buffer

芋道源码  · 公众号  · Java  · 2025-05-15 12:16

正文

请到「今天看啥」查看全文


  • change buffer
  • Log Buffer
  • Doublewrite Buffer
  • 最后

  • 今天填一下之前的坑,盘一盘 mysql 相关的 buffer。

    我们来看一下官网的一张图:

    这张图画的是 mysql innodb 的架构,从图中可以看到有很多 buffer,这篇我们就一个一个盘过去。

    发车!(文档基于mysql8.0,以下描述的存储引擎基于 mysql innodb)

    buffer pool

    首先,我们来看下 buffer pool。

    其实 buffer pool 就是内存中的一块缓冲池,用来缓存表和索引的数据。

    我们都知道 mysql 的数据最终是存储在磁盘上的,但是如果读存数据都直接跟磁盘打交道的话,这速度就有点慢了。

    所以 innodb 自己维护了一个 buffer pool,在读取数据的时候,会把数据加载到缓冲池中,这样下次再获取就不需要从磁盘读了,直接访问内存中的 buffer pool 即可。

    包括修改也是一样,直接修改内存中的数据,然后到一定时机才会将这些脏数据刷到磁盘上。

    看到这肯定有小伙伴有疑惑:直接就在内存中修改数据,假设服务器突然宕机了,这个修改不就丢了?

    别怕,有个 redolog 的存在,它会持久化这些修改,恢复时可以读取 redolog 来还原数据,这个我们后面的文章再详盘,今天的主角是 buffer 哈。

    回到 buffer pool,其实缓冲池维护的是页数据,也就是说,即使你只想从磁盘中获取一条数据,但是 innodb 也会加载一页的数据到缓冲池中,一页默认是 16k。

    当然,缓冲池的大小是有限的。按照 mysql 官网所说,在专用服务器上,通常会分配给缓冲池高达 80% 的物理内存,不管分配多少,反正内存大小正常来说肯定不会比磁盘大。

    也就是说内存放不下全部的数据库数据,那说明缓冲池需要有淘汰机制,淘汰那些不常被访问的数据页。

    按照这个需求,我们很容易想到 LRU 机制,最近最少使用的页面将被淘汰,即维护一个链表,被访问的页面移动到头部,新加的页面也加到头部,同时根据内存使用情况淘汰尾部的页面。

    通过这样一个机制来维持内存且尽量让最近访问的数据留在内存中。

    看起来这个想法不错,但 innodb 的实现并不是朴素的 LRU,而是一种变型的 LRU。

    从图中我们可以看出 buffer pool 分为了老年代(old sublist)和新生代(new sublist)。

    老年代默认占 3/8,当然,可以通过 innodb_old_blocks_pct 参数来调整比例。

    当有新页面加入 buffer pool 时,插入的位置是老年代的头部,同时新页面在 1s 内再次被访问的话,不会移到新生代,等 1s 后,如果该页面再次被访问才会被移动到新生代。







    请到「今天看啥」查看全文