postgresql15 内核源码分析-buffer查找接口

 

  • 专栏内容:postgresql内核源码分析
  • 个人主页:我的主页
  • 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

目录

前言

概述

接口介绍

调用场景分析

详细分解

结尾


前言

本文是基于postgresql 15的代码进行分析解读,演示是在centos8系统上进行。


概述

postgresql中,SQL引擎使用表文件中的数据时,先读入共享缓冲区,修改时也先在缓冲区进行修改,而后通过缓冲区替换算法,定时脏页落盘等机制将数据写入磁盘。共享缓冲区是由buffer数组构成,每一个buffer对应数据文件中的一个page,默认配置时就是8K。

前面介绍过缓冲区替换算法及查找流程,本文对查找接口进行分享介绍。

接口介绍

postgresql 主要有六种查找buffer的接口,分别在不同场景下,以提升性能。

extern PrefetchBufferResult PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,

 ForkNumber forkNum,

 BlockNumber blockNum);

extern PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum,

   BlockNumber blockNum);

extern bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum,

 BlockNumber blockNum, Buffer recent_buffer);



extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);

extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum,

 BlockNumber blockNum, ReadBufferMode mode,

 BufferAccessStrategy strategy);

extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,

ForkNumber forkNum, BlockNumber blockNum,

ReadBufferMode mode, BufferAccessStrategy strategy,

bool permanent);

调用场景分析

ReadBuffer

最简单的调用,对于普通表常用,因为只能MAIN_FORKNUM,默认访问策略,也就是NULL

ReadBufferExtended

比较灵活,可以指定forknum, mode, strategy,ReadBuffer内部也是调用此接口

ReadBufferWithoutRelcache

一般在拷贝database或table,replay wal时调用

ReadRecentBuffer

主要在replay wal时调用,与ReadBuffer相比,此接口不会去查buffer mapping hash

PrefetchBuffer

在lazyvacuum时调用,扫描表的尾部的pages

PrefetchSharedBuffer

在PrefetchBuffer会调用;此外在replay wal时调用,提前加载WAL涉及的buffer来加速

详细分解

查找buffer会有以下几种情况:

(1) 在BufferMapping hash中找到,说明当前查找的tag已经有buffer存在,直接使用buffer id再查看buffer的有效性;查找到后,需要在第一时间加pin,再释放buffermapping hash段锁;

当前buffer可能有三种情况:

一种是buffer数据已经加载成功,也就是BM_VALID,此时加pin使用即可;

另一种是当前buffer只是tag设置成功了,数据还没有加载成功,有其它backend正在加载,那么此时就等待IO完成;

还有一种情况是,tag设置成功了,数据还没有加载成功,而且没有其它backend设置IO_IN_PROGRESS,那么当前进程负责加载数据;

(2)如果hash中没有找到,说明当前的tag没有buffer,需要使用替换算法找到一个buffer,第一时间进行增加引用计数,加pin;再看此buffer是否需要刷盘或者不符合替换;找到待替换的buffer时,需要持有描述符锁,直到加pin完成才释放,避免其它backend争抢;

对于替换算法找到的buffer会存在几种情况:

一是当前buffer为脏,需要刷盘;先加内容锁,如果加上再进行判断,如果buffer对应的WAL还没有落盘时,需要重新找替换块;不符合当前替换策略时,会将当前块从查找环中踢除,然后重新查找替换块;如果加不上内容锁,说明有backend正在修改,也会放弃重新找替换块;

二是当前buffer已经有tag的,可能是非脏块,需要对替换块对应的buffermapping 段加锁;此处要对新旧tag都要加锁,注意加锁顺序,避够死锁;

三是buffer当前是无效的,可能是没有被用过,就直接替换;

四是在替换过程中,其它backend又加pin使用甚至修改变脏页,此时也需要重新查找替换块;

(3)在新旧tag替换时,先加入buffermapping中,此时有可能此它backend已经加进入去了,那么加pin,等待加载磁盘;如果是新加入buffermapping中,那么修改buffer tag,然后修改buffer 描述符的state;然后启动Io加载磁盘;


结尾

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!


http://www.niftyadmin.cn/n/203045.html

相关文章

使用new Date生成时间的问题

var anew Date(‘2023-5-7’); var bnew Date(‘2023-05-07’); var cnew Date(‘2023/5/7’); var dnew Date(‘2023/05/07’); a.getTime()的值是1683388800000 b.getTime()的值是1683417600000 b的值要比a的值大八个小时。 a、c、d的值一样。

【redis】哨兵

redis的哨兵 Markdown编辑器真好用嘿 还有模板 文章目录redis的哨兵前言一、是什么?二、能干嘛1.主从监控2.消息通知3.故障转移4.配置中心三、怎么玩(案例演示、实战步骤)1.哨兵的配置文件a.命令1: ***sentinel monitor***b.命令2…

商城项目-客服功能

最近一段时间我们在完善项目,我们在写的项目是一个商城项目。上次考核的时候考虑到进度问题,客服功能只做了一半,这次项目我对它进行了完善。 客服功能因为要实现即时通信,我主要是基于websocket实现的,它实现了浏览器…

windows10 java 创建合约

a. 安装Nodejs 主要是方便使用npm 命令 并配置环境变量 b.使用 npm 可以便捷地安装Solidity编译器solcjs npm install -g solc c.找个目录 创建一个solidity文件 如 // SPDX-License-Identifier: GPL-3.0pragma solidity >0.8.2 <0.9.0;/*** title Storage* dev Store…

Java List排序4种写法

方式1&#xff1a;JAVA中我们可以使用java.util.Collections类的sort(List list)方法对list集合中的元素排序。方式2&#xff1a;JDK8之后特别是lambda表达式的盛行&#xff0c;而且Collections的sort方法其实是调用了List接口自己的sort方法&#xff1b;所以可以使用List接口自…

第二章Python序列-列表

列表&#xff1a;1.创建列表&#xff08;1&#xff09;直接将一个列表对象赋给变量>>> a[1,2,3,4,5] >>> a [1, 2, 3, 4, 5]>>> a_list[a,b,mpilgrim,z,example] >>> a_list [a, b, mpilgrim, z, example] >>> a_list[] #创建空…

Window cmd 强制删除文件夹

SET PATHG:\360WIFI Takeown /F %PATH% /r /d y cacls %PATH% /t /e /g Administrators:F rd /s /q %PATH%

国家级贫困县摘帽情况分省分年统计(832个)

1、数据来源&#xff1a;国务院扶贫开发领导小组办公室 http://www.cpad.gov.cn/art/2020/10/16/art_343_1140.html 2、时间跨度&#xff1a;2016-2020 3、区域范围&#xff1a;全国832个贫困县 4、数据图例&#xff1a; 832个国家贫困县历年摘帽名单 一、2016年摘帽贫困…