PostgreSQL(二十二)缓冲区管理器

目录

一、缓冲区概述

1、缓冲区结构

2、buffer_tag结构

3、Backend进程读取操作

4、写脏块

二、缓冲区管理器结构

1、第一层:Buffer Table layer(缓冲区表层)

2、第二层:Buffer Descriptor Layer(缓冲区描述层)

3、第三层:buffer pool layer

4、数据的访问过程

三、缓冲区管理器锁(Buffer Manager Locks)

1、表层的锁

2、描述层的锁

3、spin lock--自旋锁/旋转锁

四、缓冲区管理器的工作原理

1、情况1:访问已存放在缓冲区中的数据块

2、情况2:加载数据块到空的缓冲池插槽

3、情况3:加载数据块到一个需要释放的缓冲池插槽

4、缓冲区块替换机制

五、环形缓冲区(Ring Buffer)

1、Bulk-reading

2、Bulk-writing

3、Vacuum-processing

六、共享池缓冲区参数设置

1、shared_buffers参数设置

2、wal_buffers 参数设置

3、effective_cache_size参数设置


一、缓冲区概述

1、缓冲区结构

缓冲区:存放各种类型的数据块

(1)数据文件页、表和索引块

(2)可用空间地图块(fsm)

(3)可见性地图块(_vm)

(4)缓冲区数组索引--buffer_ids

2、buffer_tag结构

(1)RelFileNode:分别为表对象oid、数据块oid、表空间oid

(2)页面的fork number(分别为0、1、2)(0=表和索引块,1=fsm,2=vm)

(3)页面number(页面属于哪个块)

示例:缓冲区标记:{(16821、16384、37721)、0、7}

(1)7=标识第7个块中的页

(2)0=fork号,0表明这是存放表数据的数据块

(3)37721=对象号(关系号,OID),表明是属于哪个对象的

(4)16384=数据库OID,说明该块的内容属于OID为16384的数据库

(5)16821=表空间OID,说明该块的内容属于OID 16821的表空间。

3、Backend进程读取操作

后台进程读取数据块到缓冲区的流程(图解)

4、写脏块

下面进程工作时会导致脏块写(将脏页刷新到存储区):

(1)checkpointer(检查点进程):

--将从上一个检查点以来到当前检查点为止,产生的脏块,全都写入磁盘。

--检査点进程将检査点记录写入WAL段文件,并在检查点启动时刷新脏页。

--ckpt的写是一个I/O密集型的写。

(2)background writer(后台写进程)

--后台写进程bgwr持续一点一点地刷新脏页,对数据库活动的影响最小。

--后台写进程的作用是可以减少检查点密集写的影响。

--后台写进程每200毫秒唤醒一次(由bgwriter_delay定义),最多刷新100页(由bgwriter_Iru_maxpages定义)(默认情况下)。

tip:类比oracle的bgwr和ckpt进程,不同的是:

在oracle中,ckpt会给bgwr一个写的信号,由bgwr完成全部的脏块写动作。

在PG中,检査点与后台写进程分离。pg的ckpt自己也会执行脏块写的动作,与bgwr一起写。

相比之下,PG后台写进程独立的方式可以减少ckpt在写时的I/O密集程度。

二、缓冲区管理器结构

Buffer manager’s three-layer structure--缓冲区管理器的三层结构(图解)

1、第一层:Buffer Table layer(缓冲区表层)

在这一层内置的hash函数将buffer_tags映射到插槽,插槽中记录了buffer_tags和描述层的buffer_id的映射关系。

2、第二层:Buffer Descriptor Layer(缓冲区描述层)

本层描述内容包含:buffer_tag与缓冲池插槽id的映射关系,访问次数统计,锁等信息

(1)tag:数据块的tag

(2)buffer_id:缓冲池ID

(3)refcount:记录块被访问的次数。

(4)usage_count:使用的次数,与refcount相关。两者配合使用。

(5)countext_lock and io_in_progress_lock:锁信息。访问内存缓冲区时,需要进行加锁保护。

(6)flags:内存块的标记

       --dirty bit:脏块

       --valid bit:有效块(脏块的内容被写到磁盘后,原本的脏块就变为有效块)

       --io_in_progress bit:正在写/处理的块

(7)freeNext

3、第三层:buffer pool layer

缓冲池是存储数据文件页(如表、索引)的简单数组。缓冲池数组的索引称为buffer_ids;

缓冲池被分割成大小为8k的插槽,等于页面大小。因此,每个槽可以存储整个页面。

4、数据的访问过程

第一次访问一个数据块(在缓冲区全为空时),缓冲区管理器是怎么做的:

(1)先请求一个缓冲区空间,再buffer table 层把描述层的buffer_id把buffer_tag进行映射;

(2)然后在描述层把buffer_tag与缓冲区id进行映射;

(3)最后把数据块读到相应的缓冲区槽。

访问数据块时,要怎么做:

(1)先通过buffer table层,获取A块的插槽id=0

(2)通过ID=0定位到Buffer Descriptor层,找到对应的插槽,在插槽中获得对应的buffer_id

(3)将获取的buffer_id告诉后端进程,然后后端进程根据这个buffer_id来直接访问缓冲区

三、缓冲区管理器锁(Buffer Manager Locks)

缓冲区管理器为许多不同的目的使用许多锁;

锁是缓冲区管理器同步机制的一部分,它们与任何SQL语句和SQL选项都不相关。

1、表层的锁

BufMappingLock保护整个缓冲表的数据完整性。它是一个轻量锁,可以在共亨和独占模式下使用。

在缓冲区表中搜索条目时,后端进程保存共亨的BufMappingLock。当插入或删除条目时,后端进程持有独占锁。

2、描述层的锁

每个缓冲区描述符使用两个轻量级锁

(1)content_lock:内容锁。典型的强制访问限制的锁。它可以用于共享和独占模式。

       当执行下列操作之一时,将获取独占内容锁:

              --dml操作

              --物理删除元组或压缩存储页上的可用空间(Vacuum操作和HOT处理)

              --冻结存储页中的元组

(2)io_in_progress_lock:用于等待缓冲区上的I/O完成(对数据块进行操作时)。

当pg进程从存储区加载/写入页面数据时,该进程在访问存储器时持有相应描述符的独占io_in_progress锁。

3、spin lock--自旋锁/旋转锁

如何固定缓冲区描述符:

(1)获取缓冲区描述符的自旋锁

(2)将其refcount和usage_count的值增加1

(3)松开旋转锁

如何将脏位设置为“1”:

(1)获取缓冲区描述符的自旋锁

(2)使用按位操作将脏位设置为“1”

(3)松开旋转锁

四、缓冲区管理器的工作原理

1、情况1:访问已存放在缓冲区中的数据块

(1)后端进程访问表层相关插槽;

(2)获取共享模式的BufMapping锁;

(3)通过表层获得对应描述层的插槽ID(id=2);

(4)在描述层通过获得的插槽id,获取缓冲区的buffer id;

(5)释放锁;

(6)后端进程依据获得的buffer id,直接访问缓冲池的内容,获得数据。

2、情况2:加载数据块到空的缓冲池插槽

(1)后台进程没有在缓冲区中发现这个数据块;

(2)从描述层中分配一个可用的插槽,返回插槽id

(3)获取独家模式的BufMapping锁;

(4)在表层绑定tag与id信息;

(5)将磁盘中的数据块内容读取到缓冲池;

(6)释放锁;

(7)后台进程利用从描述层获取的buffer id,直接访问缓冲区内容。

3、情况3:加载数据块到一个需要释放的缓冲池插槽

核心:先释放、再加载

(1)后台进程发现目标数据不在缓冲池中。

(2)在描述层寻找可用的插槽,发现目前插槽已满。

然后根据替换机制规则,判断出F是一个可以老化出去的块。然后将这个块的空间释放,用于存储现在需要查询的数据块。

(3)目前这个内存块存储的还是原本Tag_F映射的buffer id对应的磁盘内容;

(4)获取旧的独家模式的BufMapping锁;

(5)获取新的独家模式的BufMapping锁,并在表层插入一条新的条目。此时在表层就会有两个记录的tag同时指向了同一个描述层id(接下来的步骤需要给旧的删除);

(6)删除旧条目,释放旧的独家模式的BufMapping锁(删除后,映射关系失效);

(7)将当前需要查询的数据,从磁盘中读取到缓冲区中;

(8)释放之前获取的新的独家模式的BufMapping锁;

(9)后台进程根据获取的buffer id直接访问缓冲区读取数据。

4、缓冲区块替换机制

替换页面算法

8.1以前:LRU算法

        最近最少使用原则:热度高的表放到LRU的列表头部,热度低了就被放到列表末尾,老化放在末尾的表。

8.1及以后:时钟扫描算法

       缓冲区描述符显示为蓝色或青色框,框中的数字显示每个描述符的使用计数,每扫描一次则-1,缓冲区每被访问过一次则+1

当时钟扫描到refcount=0时,此块将会被老化。否则重复循环扫描,直到扫到0为止

五、环形缓冲区(Ring Buffer)

        当业务需要一个大块的缓冲池时,假如扫描了超过四分之一缓冲池空间(共享缓冲区/4)时,还没有找到足够的可用缓冲池,则会新分配一个环形缓冲区。这个新分配的环形缓冲池就被称为ring-buffer。

        这种情况一般会出现在大数据块操作时,例如:bulk-reading(大量加载)、bulk-writing(大量写)、vacuum-processing(空间整理).

        优点:不会因为某个特殊的大业务动作,来影响已经使用的数据缓冲区,起到一个保护作用,提高缓冲区重复利用率,降低磁盘I/O。

1、Bulk-reading

当大量加载业务需要大块的缓冲池切扫描了超过四分之一缓冲池还没找到,则会分配一个256KB的ring-buffer。

2、Bulk-writing

当大量写业务出现这种情况,会分配一个16MB的ring-buffer。

执行下面列出的sql命令时,会触发大量写业务:

       (1)COPY FROM command.

       (2)CREATE TABLE AS command.

       (3)CREATE MATERIALIZED VIEW    or    REFERSH MATERIALIZED VIEW command.

       (4)ALTER TABLE command.

3、Vacuum-processing

当自动真空机进行真空处理时出现这种情况,会分配一个256KB的ring-buffer。

六、共享池缓冲区参数设置

1、shared_buffers参数设置

show shared_buffers;
Alter system set shared_buffers=256M;

2、wal_buffers 参数设置

show wal_buffers;
Alter system set wal_buffers =4M

3、effective_cache_size参数设置

show effective_cache_size;

这个参数提供可用于磁盘高速缓存的内存量的估计值。它只是一个建议值,而不是确切分配的内存或缓存大小。它不会实际分配内存,而是会告知优化器内核中可用的缓存量。

这个值会影响执行SQL时是选择全表扫描还是优化器的决策。在一个索引的代价估计中,更高的数值会使得索引扫描更可能被使用,更低的数值会使得顺序扫描(全表扫描)更可能被使用。

在设置这个参数时,还应该考虑 Postgresql的共享缓冲区以及将被用于 Postgresql数据文件的内核磁盘缓冲区。

默认值是4GB。不建议修改,除非对于这个参数的理解以及数据库业务场景非常了解、笃定修改后会提高性能(大佬可以玩,菜鸡不要动)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/45726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

秋招Java后端开发冲刺——Mybatis使用总结

一、基本知识 1. 介绍 MyBatis 是 Apache 的一个开源项目,它封装了 JDBC,使开发者只需要关注 SQL 语句本身,而不需要再进行繁琐的 JDBC 编码。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java POJO(Plain …

Elasticsearch 建议(Suggesters):实现自动补全和拼写检查

引言 在现代搜索引擎中,自动补全和拼写检查功能已成为提升用户体验的重要工具。Elasticsearch,作为一款强大的分布式搜索和分析引擎,提供了多种Suggesters API来帮助开发者实现这些功能。本文将详细介绍Elasticsearch中的四种主要Suggester—…

Bertopic环境安装与文本主题聚类

文章目录 1.环境配置(一)安装:anaconda1. 理解:为什么需要anaconda2. 下载anaconda3. 启动anaconda(二)安装:python环境(三)安装:依赖包hdbscan的安装问题解决方案1. 安装build-tools-for-visual-studio2. 安装hdbscan(四)安装transformers、BERTopic等重要依赖包2…

【Flask从入门到精通:第八课:ORM、Flask-SQLAlchemy】

ORM ORM 全拼Object-Relation Mapping,中文意为 对象-关系映射。主要实现模型对象到关系数据库数据的映射。 ORM提供了一种面向对象操作数据库的方式给开发者。不需要编写原生SQL语句也能操作数据库,实现了业务代码与底层数据的解耦。 优点&#xff1…

Linux rpm打包(rpmbuild、spec文件)(rpmlint)(Red Hat Package Manager)(rpm包制作、安装包制作)

文章目录 RPM 打包概述定义与重要性核心组件- rpm:基本命令行工具,用于安装、查询、验证和卸载RPM包。- rpmbuild:用于构建 RPM 软件包的工具。- spec 文件:定义了如何构建 RPM 包的脚本,包括包描述、版本、构建指令等…

硬件产品经理:电子产品加工成本

目录 1、板材费用 2、SMT、THT加工 3、组装费 4、测试费 电子产品的加工主体可以分为四个大的部分: 1、板材费用 首选就是PCB的板材费用,一般是按照平米计算的,普通双层板是400左右/平米。 量产会更便宜一些。 如果沉金或其他加工工艺,成本会增加不少。 2、SMT、THT加工…

Milvus 核心设计 (4) ---- metric及index原理详解与示例(2)

目录 背景 Binary Embedding 定义与特点 常见算法 应用场景 距离丈量的方式 Jaccard Hamming 代码实现 Index BIN_FLAT BIN_IVF_FLAT Sparse embeddings 定义 应用场景 优点 实现方式 距离丈量方式 IP Index SPARSE_INVERTED_INDEX 应用场景 优势 SPAR…

零信任的架构结合模块化沙箱,实现一机两用的解决方案

零信任沙箱是深信达提出的一种数据安全解决方案,它将零信任原则与SDC沙箱技术的优势相结合。零信任原则是一种安全概念,核心思想是“永不信任,总是验证”。它要求对每一个访问请求都进行严格的身份验证和授权,无论请求来源于内部还…

从RL的专业角度解惑 instruct GPT的目标函数

作为早期chatGPT背后的核心技术,instruct GPT一直被业界奉为里程碑式的著作。但是这篇论文关于RL的部分确写的非常模糊,几乎一笔带过。当我们去仔细审查它的目标函数的时候,心中不免有诸多困惑。特别是作者提到用PPO来做强化学习,…

【微信小程序知识点】手机号验证组件

手机验证组件,用于帮助开发者向用户发起手机号申请,必须经过用户同意后,才能获得由平台验证后的手机号,进而为用户提供相应的服务。 手机号验证组件分为两种:手机号快速验证组件以及手机号实时验证组件。 1.手机号快速…

【微信小程序知识点】自定义构建npm

在实际开发中,随着项目的功能越来越多,项目越来越复杂,文件目录也变得很繁琐,为了方便进行项目的开发,开发人员通常会对目录结构进行优化调整,例如:将小程序源码放到miniprogram目录下。 &…

【C++】使用gtest做单元测试框架写单元测试

本文主要介绍在将gtest框架引入到项目里过程中遇到的问题。 我的需求如下: 用CMake构建项目。我要写一些测试程序验证某些功能,但是不想每一个测试都新建一个main函数。 因为新建一个main函数就要在CMakeList.txt里增加一个project,非常不方便。 于是我搜了下,C++里有没…

Portainer工具

Portainer是一款免费、开源的Docker的图形化管理工具,其能够提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和…

深入理解JS中的闭包

闭包是JavaScript中一个非常强大的特性,它允许函数访问并操作函数外部的变量。在深入理解闭包之前,我们需要先了解JavaScript的作用域和作用域链的概念。 1、作用域和作用域链 在JavaScript中,作用域决定了代码块中变量和其他资源的可见性。…

Flink实时开发添加水印的案例分析

在Flink中,处理时间序列数据时,通常需要考虑事件时间和水印(watermarks)的处理。以下是修改前后的代码对比分析: 修改前的代码: val systemDS unitDS.map(dp > {dp.setDeviceCode(DeviceCodeEnum.fro…

Macos 远程登录 Ubuntu22.04 桌面

这里使用的桌面程序为 xfce, 而 gnome 桌面则测试失败。 1,安装 在ubuntu上,安装 vnc server与桌面程序xfce sudo apt install xfce4 xfce4-goodies tightvncserver 2,第一次启动和配置 $ tightvncserver :1 设置密码。 然后修改配置&#xff1a…

JVM 之对象的结构与创建

1.对象的创建 1.1类加载 当Java 虚拟机遇到一条字节码 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到 一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那 必须先执行相应的类加载过…

Python MySQL 教程

Python MySQL 教程 引言 Python 是一种广泛使用的高级编程语言,以其简洁明了的语法和强大的功能而闻名。MySQL 是一种流行的开源关系数据库管理系统 (RDBMS),广泛用于各种应用程序,包括数据密集型 Web 应用程序。Python MySQL 教程将指导您如何使用 Python 语言与 MySQL 数…

C# .net6使用Hangfire

首先我们先来了解什么是Hangfire? Hangfire 是一个用于 .NET 的任务调度库,允许你在后台运行任务,而不需要依赖外部的任务队列服务或复杂的基础设施。它简化了后台任务的创建、调度和管理过程,使得在 .NET 应用程序中处理长期运行…

flutter Android端权限

flutter 中权限请求path_provider Android 6.0 - 10.0 (API level 23 - 29)Android 11 (API level 30)具体实现示例注意事项 在 Flutter 中使用 path_provider 插件获取除本应用外所有的 PDF 文件,对于不同的 Android 版本(从 Android 6.0 到 Android 14…