postgresql 使用之 存储架构 触摸真实数据的存储结构以及组织形式,存入数据库的数据原来在这里
存储架构
专栏内容:
postgresql内核源码分析
手写数据库toadb
并发编程
个人主页:我的主页
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
概述
postgresql 数据库服务运行时,数据在磁盘上是如何存储的呢?这就涉及到了存储架构。
在文件系统中,我们可以看到以目录和文件为形式的存储单元,这是物理存储架构,
这些目录和文件实际上有一定的联系和组织形式,比如最外层目录就是集群数据目录,每个数据库会有一个目录,这就是逻辑存储架构。逻辑存储架构,维护着物理磁盘文件的组织形式,物理存储架构是具体的磁盘文件的呈现方式。
逻辑存储架构
命名空间
在逻辑上,数据库有几层组织管理命名空间
集簇->表空间tablespace->数据库database->模式schema
其中 模式是数据库内核中通过数据字典来区分,所以前三项都是通过存储架构的组织,来实现物理上的空间独立。
这在前面内核分析文章中也提到,表文件的定位,也是通过tablespace/database/relation三级来唯一标识。对于集簇这个概念,通过initdb创建的就是集簇,也就是数据存入的目录,在数据库服务启动时需要指定,它通常叫做PGDATA。
数据文件
用户数据文件
有表,索引,还有对应的vm,fsm文件,都是按照命名空间的层级目录来存储
事务相关数据
由集簇级层级的空间管理,在集簇目录下有公共目录存放
其它组织文件
如表空间文件,数据字典文件,模版库,运行日志等文件,都是集簇层级的空间进行管理,在集簇目录下有各自的目录
配置文件
- 数据库配置文件
postgresql.conf
- 客户端访问控制配置文件
pg_hba.conf和pg_ident.conf
辅助文件
如版本文件,运行信息文件等,都在PGDATA根目录下
物理存储架构
- 通常用PGDATA来引用(用的是可以定义它的环境变量的名字)。PGDATA的一个常见位置是/var/lib/pgsql/data。由不同数据库实例所管理的多个集簇可以在同一台机器上共存。
- 在表或者索引超过 1GB 之后,它就被划分成1G大小的段。
第一个段的文件名和文件节点相同;随后的段被命名为 filenode.1、filenode.2等等。这样的安排避免了在某些有文件大小限制的平台上的问题(实际上,1GB只是默认的段尺寸。段尺寸可以在编译PostgreSQL时使用配置选项–with-segsize进行调整)。原则上,空闲空间映射和可见性映射分支也可以要求多个段,但实际上这很少发生。- 每个数据库都会有一个单独的目录,其中存放该库的表文件。
集簇文件结构
先初始化一个全新的数据库集簇,下面初始化并启动数据库
# 初始化postgres数据库集簇
/opt/postgres/bin/initdb -D pgtest -W# 启动数据库,监听端口指定为 8888
/opt/postgres/bin/pg_ctl -D pgtest -l logfile -o "-p 8888" start# 以命令行客户端,登陆数据库,指定端口和数据库
/opt/postgres/bin/psql -p 8888 -d postgres
下面是initdb完成后,新建了一个表空间后的集簇目录结构,
然后为了看到一些文件类型,建了临时表,unlogged表,以及索引;
中间省略了一些表的文件列表,保留了目录层级和关键的文件。
-- 表空间
create tablespace tblspc_test location '/mnt/sda1/data/pgdata/pgtblspc';-- 普通表
create table tbl_account(id integer, name varchar, address varchar, tel varchar);-- 临时表 会话退出后就会删除
create temporary table tmptbl_test(id int, c_id int);-- unlogged 表,不会记录WAL,恢复时数据全部丢失
create unlogged table unlogtbl_test(c_id int ,consumer varchar);
create index on unlogtbl_test (c_id);
经过上面的场景构造之后,现在来看一下数据库集簇下的文件和目录层次
[senllang@hatch pgdata]$ tree pgtest
pgtest
├── base
│ ├── 1
│ │ ├── 112
│ │ ├── 113
│ │ ├── 1247
│ │ ├── 1247_fsm
│ │ ├── 1247_vm
│ │ ├── 1249
......
│ │ ├── 827
│ │ ├── 828
│ │ ├── pg_filenode.map
│ │ ├── pg_internal.init
│ │ └── PG_VERSION
│ ├── 4
│ │ ├── 112
│ │ ├── 113
│ │ ├── 1247
│ │ ├── 1247_fsm
│ │ ├── 1247_vm
......
│ │ ├── 6238
│ │ ├── 6239
│ │ ├── 826
│ │ ├── 827
│ │ ├── 828
│ │ ├── pg_filenode.map
│ │ └── PG_VERSION
│ └── 5
│ ├── 112
│ ├── 113
│ ├── 1247
│ ├── 1247_fsm
│ ├── 1247_vm
│ ├── 16403
│ ├── 16403_init
│ ├── 16406
│ ├── 16406_init
│ ├── 16407
│ ├── 16407_init
│ ├── 16408
│ ├── 16408_init
│ ├── t3_16409
│ └── t3_16412
......
│ ├── 827
│ ├── 828
│ ├── pg_filenode.map
│ ├── pg_internal.init
│ └── PG_VERSION
├── global
│ ├── 1213
│ ├── 1213_fsm
│ ├── 1213_vm
│ ├── 1214
│ ├── 1232
│ ├── 1233
│ ├── 1260
│ ├── 1260_fsm
│ ├── 1260_vm
......
│ ├── pg_control
│ ├── pg_filenode.map
│ └── pg_internal.init
├── pg_commit_ts
├── pg_dynshmem
├── pg_hba.conf
├── pg_ident.conf
├── pg_logical
│ ├── mappings
│ ├── replorigin_checkpoint
│ └── snapshots
├── pg_multixact
│ ├── members
│ │ └── 0000
│ └── offsets
│ └── 0000
├── pg_notify
├── pg_replslot
├── pg_serial
├── pg_snapshots
├── pg_stat
├── pg_stat_tmp
├── pg_subtrans
│ └── 0000
├── pg_tblspc
│ └── 16388 -> /mnt/sda1/data/pgdata/pgtblspc
├── pg_twophase
├── PG_VERSION
├── pg_wal
│ ├── 000000010000000000000001
│ └── archive_status
├── pg_xact
│ └── 0000
├── postgresql.auto.conf
├── postgresql.conf
├── postmaster.opts
└── postmaster.pid
详细介绍
文件/目录 | 描述 |
---|---|
PG_VERSION | 一个包含PostgreSQL主版本号的文件 |
base | 包含每个数据库对应的子目录的子目录 |
current_logfiles | 记录当前被日志收集器写入的日志文件的文件 |
global | 包含集簇范围的表的子目录,比如pg_database |
pg_commit_ts | 包含事务提交时间戳数据的子目录 |
pg_dynshmem | 包含被动态共享内存子系统所使用的文件的子目录 |
pg_logical | 包含用于逻辑复制的状态数据的子目录 |
pg_multixact | 包含多事务(multi-transaction)状态数据的子目录(用于共享的行锁) |
pg_notify | 包含LISTEN/NOTIFY状态数据的子目录 |
pg_replslot | 包含复制槽数据的子目录 |
pg_serial | 包含已提交的可序列化事务信息的子目录 |
pg_snapshots | 包含导出的快照的子目录 |
pg_stat | 包含用于统计子系统的永久文件的子目录 |
pg_stat_tmp | 包含用于统计信息子系统的临时文件的子目录 |
pg_subtrans | 包含子事务状态数据的子目录 |
pg_tblspc | 包含指向表空间的符号链接的子目录 |
pg_twophase | 包含用于预备事务状态文件的子目录 |
pg_wal | 包含 WAL (预写日志)文件的子目录 |
pg_xact | 包含事务提交状态数据的子目录 |
postgresql.auto.conf | 一个用于存储由ALTER SYSTEM 设置的配置参数的文件 |
postmaster.opts | 一个记录服务器最后一次启动时使用的命令行参数的文件 |
postmaster.pid | 一个锁文件,记录着当前的 postmaster 进程ID(PID)、集簇数据目录路径、postmaster启动时间戳、端口号、Unix域套接字目录路径(Windows上为空)、第一个可用的listen_address(IP地址或者*,或者为空表示不在TCP上监听)以及共享内存段ID(服务器关闭后该文件不存在) |
表空间
在表空间中创建了一个临时表,一个普通表,还有一个数据库
-- 创建数据库,指定存储的表空间
create database test tablespace tblspc_test ;-- 在指定表空间创建临时表
create temporary table tmptbl_test1(id int, c_id int) tablespace tblspc_test;-- 在指定表空间创建普通表
create table tbl_salary(id integer, level float, performance float) tablespace tblspc_test;
物理结构
查看表空间目录中文件,目录层次和文件列表如下
[senllang@hatch pgdata]$ tree pgtblspc/
pgtblspc/
└── PG_16_202306141├── 16389│ ├── 112│ ├── 113│ ├── 1247│ ├── 1247_fsm│ ├── 1247_vm│ ├── 1249│ ├── 1249_fsm│ ├── 1249_vm......│ ├── 826│ ├── 827│ ├── 828│ ├── pg_filenode.map│ └── PG_VERSION└── 5├── 16395└── t3_16413
可以看到,在表空间的目录下,是一个目录 PG_16_202306141,命名以PG开头,然后是数据库版本,再加创建的日期。
用户定义的表空间都在PGDATA/pg_tblspc目录里面有一个符号连接,它指向物理的表空间目录(就是在CREATE TABLESPACE命令里指定的那个目录)。
这个符号连接是用表空间的 OID 命名的。
原理说明
在物理表空间目录中有一个名称取决于PostgreSQL服务器版本的子目录,例如PG_16_202306141(使用该子目录的原因是后续版本的数据库可以使用CREATE TABLESPACE指定相同的目录位置而不会造成冲突)。
在这个版本相关的子目录中,为每个在这个表空间里有元素的数据库都有一个子目录, 以数据库的OID命名。该目录里的表和索引遵循文件节点命名模式。
初始化集群后,有两个默认的表空间,pg_default和pg_global,当我们没有指定表空间时,创建的数据库,表等都是存放在pg_default表空间。
pg_default不需要通过pg_tblspc来访问,而是对应于PGDATA/base。类似地,pg_global表空间也不通过pg_tblspc访问,而是对应于PGDATA/global。
数据库
对于集簇里的每个数据库,在PGDATA/base里都有一个子目录对应,子目录的名字为该数据库在 pg_database里的 OID。
这个子目录是该数据库文件的缺省位置;特别值得一提的是,该数据库的系统目录存储在此。
数据文件
pg_relation_filepath()函数显示任何关系的完整路径(相对于PGDATA)。
它可以作为记住上面这么多规则的替代方法。但是记住该函数只给出关系的主分支的第一个段的名称 — 你也许需要追加一个段号或_fsm、_vm、_init来找到与该关系相关的所有文件。
表和索引文件
每个表和索引都存储在独立的文件里。
对于普通表,这些文件以表或索引的filenode号命名,它可以在pg_class.relfilenode中找到。
临时表
对于临时表,文件名的形式为tBBB_FFF,其中BBB是创建该文件的后台的后台ID,FFF是文件节点号。
空闲空间映射fsm
在每种情况下,在主文件(a/k/a 主分支)之外,每个表和索引有一个空闲空间映射,它存储表中可用空闲空间的信息。
空闲空间映射存储在一个文件中,该文件以节点号加上后缀_fsm命名。
可见性映射vm
表还有一个可见性映射,存储在一个该文件以节点号加上后缀为_vm的文件中,它用于跟踪哪些页面已知含有非死亡元组。
unlogged 表
不被日志记录的表和索引,也就是unloged table 还有第三个分支,即初始化分支,它存储在该文件以节点号加上后缀为_init的分支文件中。
初始化分支是一个适当类型的空表或空索引。
当一个不被日志记录的表由于崩溃必须被重置为空时,初始化分支被随着主分支复制,而任何其他分支则被擦除(它们会在需要时自动被重建)。
toast表
如果一个表的列中可能存储相当大的项,那么该表就会有个与之相关联的TOAST表,
它用于存储无法保留在在表行中的域值的线外存储。如果表有TOAST表,该表的pg_class.reltoastrelid链接到它的TOAST表;
临时文件
临时文件(用于如排序不能放在内存中的数据等操作)被创建在PGDATA/base/pgsql_tmp中,如果临时文件被指定在一个非pg_default表空间中则它们会被创建在该表空间的pgsql_tmp子目录中。临时文件的名称的形式为pgsql_tmpPPP.NNN,其中PPP是其所属后端的PID,而NNN用于区别该后端的不同临时文件。
结尾
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!
相关文章:

postgresql 使用之 存储架构 触摸真实数据的存储结构以及组织形式,存入数据库的数据原来在这里
存储架构 专栏内容: postgresql内核源码分析 手写数据库toadb 并发编程 个人主页:我的主页 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 概述 postgresql 数据库服务运行时,数据在磁…...

Node.Js安装与配置教程
目录 1.下载官网 2.选择安装路径 3.添加环境变量 4.验证是否安装成功 5.修改模块下载位置 (1)查看npm默认存放位置 6.在node.js安装目录下,创建两个文件夹 7.修改默认文件夹 8.测试默认位置是否更改成功 9.安装报错解决办法 10.路径未更改成功解决办法 …...

Element-Plus DatePicker获取时间戳
文章目录 0、先上答案1、渔?1-1 Element-Plus 官网1-2 溯源 Day.js 0、先上答案 <!-- 秒 --><el-date-pickerv-model"timeStamp"type"datetime"value-format"X"/><!-- 毫秒 --><el-date-pickerv-model"tim…...

【算法第十五天7.29】513.找树左下角的值 112. 路径总和 106.从中序与后序遍历序列构造二叉树
链接力扣513-找树左下角的值 思路 class Solution {public int findBottomLeftValue(TreeNode root) {Queue<TreeNode> queue new LinkedList<>();queue.offer(root);int res 0;while(!queue.isEmpty()){int size queue.size();for(int i 0; i < size; i)…...

Java thymeleaf bug排查记录
刚学Java 做项目时报了一个错误 一时间看的莫名其妙 EL1008E: Property or field createTime cannot be found on object of type java.util.HashMap - maybe not public or not valid? 随即向上排查至第一个报错,发现是thymeleaf渲染时报错。 Exception proces…...

互感和励磁电感(激磁电感)的关系
互感器,变压器,他们之间有着千丝万缕的联系,自感,互感,激磁电感,漏感、耦合系数、理想互感器、理想变压器,这些东西的概念理解和相互之间的关系式。都搞明白了吗?...

stdexcept和exception,两个头文件的区别?
stdexcept和exception是C标准库中的两个头文件,它们的区别如下: 1. 引用方式:stdexcept是exception的父类,引用时可以通过引用stdexcept来自动引用exception,也可以直接引用exception。 2. 异常处理:std…...

openCV图像的读写操作
文章目录 一、数组下标二、指针 void QuickDemo::pixel_visit_demo(cv::Mat &image) {int w image.cols;int h image.rows;int dim image.channels();for (int row 0; row < h; row){for (int col 0; col < w; col){if (dim 1)//灰度图像{int pv image.at<…...

Android平台GB28181设备接入端如何降低资源占用和性能消耗
背景 我们在做GB28181设备接入模块的时候,考虑到好多设备性能一般,我们一般的设计思路是,先注册设备到平台侧,平台侧发calalog过来,获取设备信息,然后,设备侧和国标平台侧维持心跳,…...

Android Studio安装AI编程助手Github Copilot
csdn原创谢绝转载 简介 文档链接 https://docs.github.com/en/copilot/getting-started-with-github-copilot 它是个很牛B的编程辅助工具,装它,快装它. 支持以下IDE: IntelliJ IDEA (Ultimate, Community, Educational)Android StudioAppC…...

windows部署springboot项目 jar项目 (带日志监听和开机自起脚本)
windows部署springboot项目 jar项目 (带日志监听) 1.把项目打包成jar包,本例演示打包后的jar文件名为demo.jar ———————————————— 2.需要装好java环境,配置好JAVA_HOME,CLASSPATH,PATH等…...

【数据结构和算法】排序算法
说明:以下排序如无特别说明,都是从小到大升序排序 1. 冒泡排序 核心思想:每个元素与其相邻元素比较,如果前者大于后者则交换,每次循环结束后会将最大值放到最后,像小水泡从底下冒到上面成大水泡一样&…...

Error: Cannot find module ‘@babel/core’处理
Error: Cannot find module babel/core’处理 问题产生的原因如何解决 在安装babel的时候,遇到个**Error: Cannot find module babel/core’**问题,查了很多资料才解决,希望能够帮助到各位兄弟。 问题产生的原因 babel-loader和babel-core版…...

K8S系列文章之 自动化运维利器 Fabric
Fabric 主要用在应用部署与系统管理等任务的自动化,简单轻量级,提供有丰富的 SSH 扩展接口。在 Fabric 1.x 版本中,它混杂了本地及远程两类功能;但自 Fabric 2.x 版本起,它分离出了独立的 Invoke 库,来处理…...

flask--->CBV/模板/请求响应/session
CBV 1 cbv写法-1 写个类,继承MethodView-2 在类中写跟请求方式同名的方法-3 注册路由:app.add_url_rule(/home, view_funcHome.as_view(home)) #home是endpoint,就是路由别名2 cbv加装饰器-方式一:class Home(MethodView):decor…...

Go语言基础:运算符、文件操作、接口、Packages、if else、for循环
文章目录 1.运算符2.文件操作3.接口4.Packages5.If else6.For循环 1.运算符 func main() {// 算术运算符a, b : 3, 7c : a bd : a - be : a * bf : a / bg : a % baa--fmt.Println(c, d, e, f, g)// 关系运算符fmt.Println(a b)fmt.Println(a ! b)fmt.Println(a < b)fmt.…...

2308C++学习简单协程文档
调试 用gdb/lldb p __coro_frame p __promise试 Try有三种状态:无状态,有异常,有值. 条件变量 主要区别在简单异步中条件变量面向Lazy协程.在条件变量上阻塞协程时,不会阻塞当前线程.用于多个协程间交互协作.基于协程版条件变量,多个协程可实现典型生产者消费者模型. 通知…...

C++笔记之从数组指针到函数数组指针(使用using name和std::function)
C笔记之从数组指针到函数数组指针(使用using name和std::function) 参考笔记: C之指针探究(三):指针数组和数组指针 C之指针探究(十三):函数指针数组 C之指针探究(二):一级指针和一维数组 C之指针探究(十一):函数名的…...

【数据结构】常见的排序算法
常见的排序算法 常见的排序算法插入排序之直接插入排序时间复杂度特性总结 插入排序之希尔排序时间复杂度 选择排序之直接选择排序特性总结 选择排序之堆排序时间复杂度特性总结 交换排序之冒泡排序特性总结 交换排序之快速排序hoare版本挖坑法双指针法快速排序的优化1…...

CentOS 安装 Jenkins
本文目录 1. 安装 JDK2. 获取 Jenkins 安装包3. 将安装包上传到服务器4. 修改 Jenkins 配置5. 启动 Jenkins6. 打开浏览器访问7. 获取并输入 admin 账户密码8. 跳过插件安装9. 添加管理员账户 1. 安装 JDK Jenkins 需要依赖 JDK,所以先安装 JDK1.8。输入以下命令&a…...

前端如何设置表格边框样式和单元格间距?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 实现思路⭐ 代码演示⭐ 注意事项⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴…...

Ubuntu 22.04安装搜狗输入法
Ubuntu 22.04安装搜狗输入法 ubtuntu 22.04安装搜狗输入法 1. 添加中文语言支持2. 安装fcitx输入法框架3. 设置fcitx为系统输入法4. 设置fcitx开机启动,并卸载ibus输入法框架5. 安装搜狗输入法6. 重启电脑,调出搜狗输入法 1. 添加中文语言支持 Setti…...

【C++】初阶 --- 内联函数(inline)
文章目录 🥞内联函数🍟1、C语言实现"宏函数"🍟2、内联函数的概念🍟3、内联函数的特性🍟4、总结 🥞内联函数 🍟1、C语言实现"宏函数" 🥰用C语言先来实现普通的…...

VGGNet剪枝实战:使用VGGNet训练、稀疏训练、剪枝、微调等,剪枝出只有3M的模型
摘要 本文讲解如何实现VGGNet的剪枝操作。剪枝的原理:在BN层网络中加入稀疏因子,训练使得BN层稀疏化,对稀疏训练的后的模型中所有BN层权重进行统计排序,获取指定保留BN层数量即取得排序后权重阈值thres。遍历模型中的BN层权重&am…...

【iOS】GCD深入学习
关于GCD和队列的简单介绍请看:【iOS】GCD学习 本篇主要介绍GCD中的方法。 栅栏方法:dispatch_barrier_async 我们有时候需要异步执行两组操作,而且第一组操作执行完之后,才能开始执行第二组操作,当然操作组里也可以包含一个或者…...

Webpack开启本地服务器;HMR热模块替换;devServer配置;开发与生成环境的区分与配置
目录 1_开启本地服务器1.1_开启本地服务器原因1.2_webpack-dev-server 2_HMR热模块替换2.1_认识2.2_开启HMR2.3_框架的HMR 3_devServer配置3.1_host配置3.2_port、open、compress 4_开发与生成环境4.1_如何区分开发环境4.2_入口文件解析4.3_区分开发和生成环境配置 1_开启本地服…...

opencv 31-图像平滑处理-方框滤波cv2.boxFilter()
方框滤波(Box Filtering)是一种简单的图像平滑处理方法,它主要用于去除图像中的噪声和减少细节,同时保持图像的整体亮度分布。 方框滤波的原理很简单:对于图像中的每个像素,将其周围的一个固定大小的邻域内…...

Kubernetes关于cpu资源分配的设计
kubernetes资源 在K8s中定义Pod中运行容器有两个维度的限制: 资源需求(Requests):即运行Pod的节点必须满足运行Pod的最基本需求才能运行Pod。如 Pod运行至少需要2G内存,1核CPU。(软限制)资源限额(Limits):即运行Pod期间,可能内存使用量会增加,那最多能使用多少内存,这…...

Flink读取mysql数据库(java)
代码如下: package com.weilanaoli.ruge.vlink.flink;import com.ververica.cdc.connectors.mysql.source.MySqlSource; import com.ververica.cdc.connectors.mysql.table.StartupOptions; import com.ververica.cdc.debezium.JsonDebeziumDeserializationSchema; import org…...

小程序学习(五):WXSS模板语法
1.什么是WXSS WXSS是一套样式语言,用于美化WXML的组件样式,类似于网页开发中的CSS 2.WXSS和CSS的关系 WXSS模板样式-rpx 3.什么是rpx尺寸单位 4.rpx的实现原理 5.rpx与px之间的单位换算* WXSS模板样式-样式导入 6.什么是样式导入 使用WXSS提供的import语法,可以导入外联的样式…...