天天看点

pgsql本地缓冲区源码分析

下面开始对pgsql源码中缓冲区进行一个简单的分析,目的指在弄懂缓冲区的实现方式,以及如何在这个方式上面实现其他的LRU替换算法

ps:找到一篇优秀的博客,专门讲pgsql中缓冲区部分的代码

http://blog.sina.com.cn/s/articlelist_1221155353_0_4.html

1、首先pgsql来看下源码目录

pgsql本地缓冲区源码分析

pgsql中的缓冲区分为两个部分,一个部分是本地缓冲区,用来缓冲一些临时结果文件,例如Query execution plans查询的临时文件。

第二个部分是共享缓冲区,共享缓冲区存放表数据和索引数据。

PostgreSQL中缓冲区管理主要分为共享缓冲区和管理和本地缓冲区管理两大部分,其中本地缓冲区结构以及管理方法主要定义在文件pgsql/src/backend/storage/buffer/localbuf.c中,在文件最开始的注释里写道:本地缓冲区管理器对临时表进行快速的缓冲区管理,这些临时表从来不需要被记录日志或者设检查点。因此我们可以知道本地缓冲的创建和维护主要是为了对数据库系统运行过程中产生的临时关系表进行管理。

2、两个缓冲区分为两个部分

首先对本地的缓冲区进行分析,因为本地的缓冲区是缓冲一些查询的临时文件,所以不存在日志写的问题,那么实际缓冲区的算法就是最简单的时钟置换的方法。这种时钟置换的方法,是通过计数来判断数据的冷热,并没有维护所谓的LRU链表来实现的。

本地的缓冲区主要在localbuf.c中,主要有以下四个函数:

pgsql本地缓冲区源码分析

首先看下定义的全局变量,也就是维护本地缓冲区的一些常见的数据结构

pgsql本地缓冲区源码分析

一个是缓冲区的个数,每一个缓冲块都对应有一个元数据描述块,和一个引用计数,这个引用计数表示当前是否有进程占用这个用户。

然后看下如何初始化这个缓冲区的:

pgsql本地缓冲区源码分析

采用的是懒惰的初始化方式,因为大多数查询(特别是多用户的查询)都不会涉及本地缓冲区,所以PostgreSQL在查询的开始并不真正给它分配本地缓冲区,只有这个查询确实需要时才会给它分配实际空间,所以这个函数所做的工作只是创建缓冲区头部。

创建缓冲区的头部,并且将对应的缓冲描述块都置为初始化。

然后最重要的就是,当数据进入缓冲区的时候,如何分配一个缓存块呢?调用的就是如下的函数:

pgsql本地缓冲区源码分析

它是按照以下的步骤进行的:

是否在缓冲区命中,命中则直接返回

未命中,寻找当前没有被占用的块,即对应块的计数为0

寻找到没有占用的块,则判断这个块是否是脏页,如果是脏页则需要写回到闪存上

找到了对应的缓冲区地址,则开辟一个数据块的大小空间数据,写入到替换移除的数据块上。

给新填入的数据块设置一些描述信息

pgsql本地缓冲区源码分析
pgsql本地缓冲区源码分析
pgsql本地缓冲区源码分析
pgsql本地缓冲区源码分析

最后还提供了一些写出本地缓冲区的函数,这个函数的功能是将缓冲区的数据刷到闪存上,但是实际并没有移除,只是设置了脏数据

pgsql本地缓冲区源码分析