【PostgreSQL内核学习(十八)—— 存储管理(存储管理的体系结构)】
存储管理
- 概述
- 存储管理器的体系结构
- 存储管理器的主要任务
- 读写元组过程
声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
本文主要参考了《PostgresSQL数据库内核分析》一书以及一些相关参考资料
概述
数据库管理系统(DBMS)的本质是向存储设备上写入数据或者读出数据,因此存储的管理是一项非常基础且重要的技术。在 PostgreSQL 中,存储管理器是专门负责管理存储设备的模块,其提供了一组统一管理外存和内存的功能模块。因此从本质上看,存储管理器提供了 PostgreSQL 与物理存取设备的接口。因为外存对应着各种磁盘设备,而内存则对应着各种随机存储器。存储管理器是整个 PostgreSQL 系统的底层模块,各种需要访问底层硬件的操作都需要调用其提供的接口。数据库存储管理系统的一般组件和功能的描述如下所示:
- 缓存管理: 这是数据库系统的核心部分,负责缓存数据页以提高访问速度。它与磁盘存储进行交互,将频繁访问的数据页保存在内存中,以减少直接的磁盘 I/O 操作。
- 基础存储管理: 这一层处理与磁盘的实际交互,包括数据页的读写。它确保数据能够持久化存储在磁盘上,并在需要时加载到缓存中。
- 大对象存储: 数据库中的大对象(如文本或图像)通常需要特殊的存储管理,因为它们的大小通常超过标准数据页的大小。
- 内存/日志文件管理: 这部分负责管理事务日志,确保所有的数据库操作都可以在系统故障后进行恢复。日志文件通常存储了所有的事务操作记录。
- 数据库备份与恢复: 这部分涉及到的操作包括数据库的备份,以及在数据丢失或损坏时的恢复。
- 空间管理: 数据库需要跟踪磁盘上的可用空间,这通常涉及到文件空间管理(FSM)和可见性图(VM),以跟踪哪些页是空的,哪些页是可见的。
- 垃圾回收: 为了优化存储空间和性能,数据库需要定期进行垃圾回收,如 PostgreSQL 中的 VACUUM 操作。这个过程包括清理不再需要的数据,如已删除的行。
- 可视化文件描述符(VFD): 这可能是指管理文件描述符的组件,这些是操作系统提供的用于引用打开文件的句柄。
- 进程间通信(IPC): 数据库系统可能包括多个进程或线程,这个部分负责这些进程之间的通信。
- 并发控制: 数据库系统必须处理多个并发操作,这部分负责管理并发访问,保证事务的隔离性和一致性。
- 索引管理: 数据库使用索引来快速定位数据,这部分负责索引的创建、维护和优化。
- 外部接口: 数据库需要与外部世界进行交互,例如,通过 SQL 接口与用户或其他系统通信。
存储管理器的体系结构
PostgreSQL存储管理器主要包括两个功能:内存管理与外存管理。存储管理器的体系结构如下图所示:

- 内存管理: 负责共享内存管理以及进程本地内存的管理。在共享内存中存储着所有进程的共享数据,包括锁变量,进程通信状态,缓冲区等。而本地内存为各个后台进程所有,是它们的工作区域,存储着属于该进程的 Cache、事务管理信息、进程信息等。为了防止多个进程并发地访问共享数据,PostgreSQL 还提供了轻量级的锁,用于支持对共享数据的互斥访问。此外,存储管理器还提供了内存上下文(MemoryContext)用于统一管理内存的分配与回收,从而更加安全有效地对内存空间进行管理;
- 外存管理: 负责表文件管理、空闲空间管理、虚拟文件描述符管理以及大数据存储管理等。在 PostgreSQL 中,每个表都用表文件存储,表文件以表的 OID 命名。当一个表文件超过文件大小限制时,PostgreSQL会自动将其切分为多个文件进行存储,并在 OID 的基础上加上编号作为该文件的名字。每个表除了表文件以外,还有两个附属文件:可见性映射表文件(VM),空闲空间映射表文件(FSM)。前者用于加快清理操作(VACUUM),后者则用于对表的空闲空间进行管理。为了避免打开的文件超过 OS 的限制,存储管理器还引入了虚拟文件描述符管理的机制。此外,存储管理器还提供了大对象机制以及 TOAST 机制用于支持对大数据的存储。
PostgreSQL 的存储管理是为了优化和保证数据库操作的效率和安全。内存管理负责处理运行时数据和进程间的快速交互,而外存管理确保数据持久性和有效的空间利用。通过这样的机制,PostgreSQL 能够高效地处理大量数据,支持高并发的数据库操作,并且提供了数据的持久化存储和恢复能力。同时,这种架构也支持了大数据和复杂数据类型的存储,满足现代应用对数据库的多样化需求。
PostgreSQL 的存储管理器采用与操作系统类似的分页存理方式,即据在内存中是以页面块的形式存在。每个表文件由多个 BLCKSZ (一个可配置的常量) 字节大小的文件块组成,每个文件块又可以包含多个元组。表文件以文件块为单位读入内存中,每一个文件块在内存中形成一个页面块。由于页面块是文件块在内存中的存在形式,因此在后文中如不进行特殊说明也会使用页面来指代文件块。同样,文件的写入也是以页面块为单位。PostgreSQL 采用传统的行式存储,即以元组为单位进行数据的存储。一个文件块中可以存放多个元组,但是 PostgreSQL 不支持元组的跨块存储,每个元组最大为 MaxHeapTupleSize。这样保证了每个文件块中存储的是多个完整的元组。
与操作系统一样,PostgreSQL在内存中开辟了缓冲区域用于存储这些文件块,我们将其在内存中开辟的缓冲区域称为缓冲池,缓冲池被划分成若于个固定大小(和文件块的尺寸相同,也是 BLCKSZ)的缓冲区,磁盘上的文件块读入内存后被存放在缓冲区中,称之为页面块或者缓冲块。BLCKSZ 的默认值是 8192,因此一个标准缓冲块的大小默认为 8KB。
用 AI 生成了一张图,但貌似有点抽象。。。

存储管理器的主要任务
总的来说,存储管理器的主要任务包括:
- 缓冲池管理: 为了提高事务执行的效率,事务在执行时,首先会先把数据放入的缓冲区中,PostgreSQL设立了进程间共享的缓冲池以及进程私有的缓冲池。
- Cache机制: 将进程最近使用的一些数据缓存到其私有内存中,其级别高于缓冲池。
- 虚拟文件描述符(VFD)管理: PostgreSQL 通过 VFD 来对物理文件进行管理,避免因为操作系统对进程打开文件数的限制出现错误。
- 空闲空间管理: PostgreSQL 通过 FSM 快速定位到表文件中的空闲空间以便插入新数据,从而提高对空间的利用率。
- 进程间通信机制(IPC): PostgreSQL 是一个多进程系统,IPC 用来在多个后台进程间进行通信和消息传递。
- 大数据存储管理: 提供大对象和 TOAST 机制。大对象是一种由用户控制的大数据存储方法,它由用户调用函数,通过 SQL 语句直接向表中插入一个大尺寸文件。而 TOAST 机制则是在用户插入变长数据超过一定限度时自动触发的,用户无法对其加以控制。(但是可以更改存储模式,比如说)
读写元组过程
当一个 PostgreSQL 进程从数据库中读写一个元组时,对于以上各个功能模块的使用顺序如下图所示:

- 读取一个元组数据时,首先需要先获取表的基本信息,如表OID、索引信息以及统计信息,这些信息分散在多个系统表中。因此读写一个表需要访问多个系统表,但是这些每次都去读取系统表是没有必要的。因此每个进程在都会在本地内存区域设置两种 Cache,分别保存系统表元组与存储表的基本信息,从而使得进程能够快速地构建出表的基本信息和元组的模式结构。
- 获取表基本信息和元组的模式信息后,需要从元组所在的文件块中获取元组数据。这时首先判断元组所在的文件块是否在缓冲池里面,若是则直接返回,否则需要从存储介质中读取相应的文件块到缓冲区中,再从缓冲区中读取元组。
- 缓冲区与存储介质的交互是通过存储介质管理器(SMGR)进行。不同存储介质的底层实现各有差异,SMGR 负责统管各种存储介质,并对上层请求提供统一的接口,对下层则根据不同的介质调用相应的介质管理器,因此 SMGR 是 PostgreSQL 外存管理的核心。
- 在磁盘管理器与物理文件之间还存在一层虚拟文件描述符机制(VFD),这是为了防止PostgreSQL 打开的文件数超过 OS 限制而引起不可预知的错误。VFD 机制通过合理利用有限个实际文件描述符为 PostgreSQL 提供了虚拟的无限的文件描述符。
- 在写入元组的时候,当目标表的目标文件块容量不足时,需要查找该表中具有空闲区域的文件块读入内存。但是如果遍历该表所有的文件块,效率是很低的。为了加快查找的速度,PostgreSQL 为每个表增加了一个附属文件(FSM)用于记录每个文件块的空闲空间大小,通过一定的查找机制和数据组织实现文件块的快速选择。
- 在删除元组时,PostgreSQL 使用标记的方法快速处理。该元组的物理清除工作将由VACUUM 机制来完成。当然,如果 VACUUM 依次遍历所有的文件块也是非常慢的,于是 PostgreSQL 设计了一个可见性映射表(VM)来加快查找速度。
- 除了一般的数据外,PostgreSQL 还提供了大对象机制与 TOAST 机制存储大对象数据。前者发生在用户需要为数据库存储一个大文件时,PostgreSQL 为用户提供一个创建大对象的接口函数用于存储并获得一个大对象 OID。后者则主要用于变长字符串。
相关文章:
【PostgreSQL内核学习(十八)—— 存储管理(存储管理的体系结构)】
存储管理 概述存储管理器的体系结构存储管理器的主要任务读写元组过程 声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。 本文主要参考…...
Android的组件、布局学习
介绍 公司组织架构调整,项目组需要承接其他项目组的android项目,负责维护和开发新需求,故学习下基础语法和项目开发。 组件学习 Toolbarheader布局部分 就是app最顶部的部分 他的显示与否,是与F:\androidProject\android_lear…...
【离散数学】——期末刷题题库(树其一)
🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:…...
光模块市场分析与发展趋势预测
光模块是光通信领域的重要组成部分,随着数字经济,大数据,云计算,人工智能等行业的兴起,光模块市场经历了快速发展,逐渐在数据中心、无线回传、电信传输等应用场景中得到广泛应用。本文将基于当前光模块全球…...
Python轴承故障诊断 (八)基于EMD-CNN-GRU并行模型的故障分类
目录 前言 1 经验模态分解EMD的Python示例 2 轴承故障数据的预处理 2.1 导入数据 2.2 制作数据集和对应标签 2.3 故障数据的EMD分解可视化 2.4 故障数据的EMD分解预处理 3 基于EMD-CNN-GRU并行模型的轴承故障诊断分类 3.1 训练数据、测试数据分组,数据分ba…...
鸿蒙实现年月日十分选择框,支持年月日、月日、日、年月日时分、时分切换
import DateTimeUtils from ./DateTimeUtils;CustomDialog export default struct RQPickerDialog {controller: CustomDialogControllertitle: string 这是标题TAG: string RQPickerDialog// 0 - 日期类型(年月日) 1 - 时间类型(时分&a…...
IntelliJ IDE 插件开发 | (三)消息通知与事件监听
系列文章 IntelliJ IDE 插件开发 |(一)快速入门IntelliJ IDE 插件开发 |(二)UI 界面与数据持久化IntelliJ IDE 插件开发 |(三)消息通知与事件监听 前言 在前两篇文章中讲解了关于插件开发的基础知识&…...
VUE小知识点
Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。 Vue 的主要作用是帮助开发者构建现代 Web 应用程序。它允许前端开发人员专注于应用程序…...
深入了解常见的应用层网络协议
目录 1. HTTP协议 1.1. 工作原理 1.2. 应用场景 1.3. 安全性考虑 2. SMTP协议 2.1. 工作原理 2.2. 应用场景 2.3. 安全性考虑 3. FTP协议 3.1. 工作原理 3.2. 应用场景 3.3. 安全性考虑 4. DNS协议 4.1. 工作原理 4.2. 应用场景 4.3. 安全性考虑 5. 安全性考虑…...
网络爬虫 多任务采集
一、JSON文件存储 JSON,全称为 JavaScript 0bject Notation,也就是JavaSript 对象标记,它通过对象和数组的组合来表示数据,构造简洁但是结构化程度非常高,是一种轻量级的数据交换格式。本节中,我们就来了解如何利用 P…...
真实并发编程问题-1.钉钉面试题
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术🔥如果感觉博主的文章还不错的…...
基于vue+element-plus+echarts制作动态绘图页面(柱状图,饼图和折线图)
前言 我们知道echarts是一个非常强大的绘图库,基于这个库,我们可以绘制出精美的图表。对于一张图来说,其实比较重要的就是配置项,填入不同的配置内容就可以呈现出不同的效果。 当然配置项中除了样式之外,最重要的就是…...
2312llvm,02前端
前端 编译器前端,在生成目标相关代码前,把源码变换为编译器的中间表示.因为语言有独特语法和语义,所以一般,前端只处理一个语言或一组类似语言. 比如Clang,处理C,C,objective-C源码. 介绍Clang Clang项目是C,C,Objective-C官方的LLVM前端.Clang的官方网站在此. 实际编译器(…...
【MATLAB源码-第101期】基于matlab的蝙蝠优化算BA)机器人栅格路径规划,输出做短路径图和适应度曲线。
操作环境: MATLAB 2022a 1、算法描述 蝙蝠算法(BA)是一种基于群体智能的优化算法,灵感来源于蝙蝠捕食时的回声定位行为。这种算法模拟蝙蝠使用回声定位来探测猎物、避开障碍物的能力。在蝙蝠算法中,每只虚拟蝙蝠代表…...
【数据结构】二叉树的模拟实现
前言:前面我们学习了堆的模拟实现,今天我们来进一步学习二叉树,当然了内容肯定是越来越难的,各位我们一起努力! 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:数据结构 👈 &…...
open3d bug:pcd转txt前后位姿发生改变
1、open3d bug:pcd转txt前后位姿发生改变 open3d会对原有结果进行一个微小位姿变换 import open3d as o3d import numpy as np# 读取PCD点云文件 pcd o3d.io.read_point_cloud(/newdisk/darren_pty/zoom_centered_s2.pcd)# 获取点云坐标 points pcd.points# 指定…...
持续集成交付CICD:Jenkins使用GitLab共享库实现基于Ansible的CD流水线部署前后端应用
目录 一、实验 1.部署Ansible自动化运维工具 2.K8S 节点安装nginx 3.Jenkins使用GitLab共享库实现基于Ansible的CD流水线部署前后端应用 二、问题 1.ansible安装报错 2.ansible远程ping失败 3. Jenkins流水线通过ansible命令直接ping多台机器的网络状态报错 一、实验 …...
OpenAI 疑似正在进行 GPT-4.5 灰度测试!
大家好,我是二狗。 今天,有网友爆料OpenAI疑似正在进行GPT-4.5灰度测试! 当网友询问ChatGPT API调用查询模型的确切名称是什么时? ChatGPT的回答竟然是 gpt-4.5-turbo。 也有网友测试之后发现仍然是GPT-4模型。 这是有网友指…...
DC-6靶场
DC-6靶场下载: https://www.five86.com/downloads/DC-6.zip 下载后解压会有一个DC-3.ova文件,直接在vm虚拟机点击左上角打开-->文件-->选中这个.ova文件就能创建靶场,kali和靶机都调整至NAT模式,即可开始渗透 首先进行主…...
单片机应用实例:LED显示电脑电子钟
本例介绍一种用LED制作的电脑电子钟(电脑万年历)。其制作完成装潢后的照片如下图: 上图中,年、月、日及时间选用的是1.2寸共阳数码管,星期选用的是2.3寸数码管,温度选用的是0.5寸数码管,也可根据…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
