暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据库内核buffer的管理机制

原创 会飞的鱼 2024-06-10
119

大家好,我是会飞的鱼。

作为一个数据库领域的新人,我将学习PostgreSQL数据库的内核,计划将其中的知识进行整理,先阐述原理,后介绍代码中的实现。目前打算从存储引擎开始学起。

好,废话不多说,我们先开始介绍缓存区的设计。

1. buffer区的基本介绍

数据会在磁盘上进行存储,操作系统会以页的形式进行管理。当我们修改数据,我们需要将这一页从磁盘上读上来,放在内存中,从而进行对应的修改。为了更好的区分概念,页在磁盘中称之为block,在内存中称之为buffer。


如图1所示,磁盘中存了许多文件,每个文件长度不一,按照page进行大小管理(page一般为4K大小)。页面从磁盘加载到内存中的缓存池。当节点又一次还要查看同一个block的内容,我们可以在内存中找到它,无需再从磁盘加载,减少IO时间。

缓存区的大小是有限制的,当缓存区的buffer不够时,我们需要选出一个buffer进行淘汰,在页面淘汰前,如果页面发生修改,页面需要先刷到磁盘,即写入到磁盘中的对应位置。但页面刷到此盘后,这个buffer就可以存储其他页面。

对于同一个页面编号,例如 (file1-page1),存在磁盘中block,也存在buffer。当buffer发生修改,我们将buffer设置为脏页,这一过程称之为置脏。当页面变成脏页后,我们会将页面收集起来,定期再刷回磁盘,从而做到页面的内存和磁盘一致。

2.页面上的管理

对于页面1)从磁盘加载到内存中和2)从内存写到磁盘,这些操作也是需要在锁的保护下,在PG代码中对应着IO锁。

对于页面内容的读取和修改,也是需要在锁的保护下,在PG代码中对应这内容锁。当然,读页面需要以S锁的方式获取内容锁,写页面需要以X锁的方式获取内容锁。

数据库还需要记录buffer区上有哪些页面,哪一个页面对应者哪一个buffer,在PG中bufTable就是做这件事。bufTable是一个hash表,可以通过页面的编号(BufferTag)查到,对应页面是否在bufTable中。

这里介绍一下PG的设计:

第一次操作页面,

1)从bufTable找对应页面,没有找到;

2)找到一个空闲的buffer,pin住buffer;

3)获取buffer的IO锁,从磁盘加载页面,buffer才是一个有效的buffer;

4)对于buffer的内容锁进行加锁 ;

5)进行对应查看/修改;

6)释放内容锁;

7)对于buffer进行unpin。

第二次操作页面,

1)从bufTable找对应页面,此时是可以找到;

2)找到对应的buffer,pin住对应buffer;无需再次从磁盘加载;

3)还是对buffer内容锁进行加锁;

4)进行对应查看/修改;

5)释放内容锁;

6)对于buffer进行unpin。

简单介绍一下pin的概念,当年准备访问buffer时,你需要pin住这个buffer,代表这个buffer正在被你使用,这样这个buffer无法被其他线程淘汰。当你不访问buffer时,就需要解pin。同时buffer也可以被多个线程同时pin住,通过引用计数记录,usage_count。当pin主一次时,这个buffer对应的引用计数就加一。

3.页面淘汰

内存是有限的,页面无法一直存储在内存中。如果buffer内存池满了,此时还需要加载,那我们需要将内存池中不用的页面进行淘汰掉。当然如果这个页面是脏页,还需要先将页面写到磁盘,再进行淘汰。对于buffer的淘汰,我们也希望淘汰一些不常访问的页面(冷页),保留经常访问的页面(热页)。所以在多数数据库中,LRU(最近最少使用)策略成为了buffer淘汰的常用策略。

PG稍稍有一些不一样,不是严格的LRU,而是采取clock sweep算法,属于NFU(Not Frequently Used)。


引入概念,访问次数(usage count),当buffer被pin住的时候,访问次数就会加一

clock sweep算法:

1.从上次遍历位置开始,第一次可以从第一个buffer

2.如果buffer被pin住,该buffer无法淘汰,跳过。对应这图片中的1

3.如果buffer没有pin住,当访问次数大于0的时候 ,将访问次数减一,对应图片中的2,如果访问次数等于0,这个buffer就是淘汰的buffer。

4.当找到淘汰的buffer,记录本次位置,下次从这个位置继续遍历。

我们不难看出找到的buffer不是严格意义上的最近未使用的buffer,存在还没有遍历到的buffer比要淘汰的buffer更不经常访问。但这并不代表这个算法不好,我个人认为,能找到相对而言的冷页进行淘汰即可,无需严格找到最不经常使用。后续对应页也会遍历到,从而被淘汰。开销小,一般实现LRU策略需要维护链表进行记录,开销大。

参考资料

https://www.interdb.jp/pg/pgsql08.html

这里简单介绍一下,clock sweep算法图来自这个网站,这个网站还是比较详细介绍PG中各种概念,是一份非常好的指南,通俗易懂,非常适合新手。笔者十分推荐该文档

如果觉得写的不错,也可以关注我的公众号。作为一个新人,刚写公众号,希望能获取大家的支持

公众号:会飞的鱼flying


最后修改时间:2024-06-10 15:12:41
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论