IT评测·应用市场-qidao123.com

标题: postgresql 利用之 存储架构 触摸真实数据的存储结构以及构造形式,存入数 [打印本页]

作者: 卖不甜枣    时间: 2024-9-27 16:51
标题: postgresql 利用之 存储架构 触摸真实数据的存储结构以及构造形式,存入数
存储架构


   ​专栏内容
postgresql内核源码分析
手写数据库toadb
并发编程
个人主页:我的主页
座右铭:天行健,君子以发奋图强;地势坤,君子以厚德载物.
  概述

   postgresql 数据库服务运行时,数据在磁盘上是怎样存储的呢?这就涉及到了存储架构。
在文件体系中,我们可以看到以目录和文件为形式的存储单元,这是物理存储架构,
这些目录和文件实际上有肯定的联系和构造形式,好比最外层目录就是集群数据目录,每个数据库会有一个目录,这就是逻辑存储架构。
  逻辑存储架构,维护着物理磁盘文件的构造形式,物理存储架构是详细的磁盘文件的呈现方式。
  逻辑存储架构

命名空间

   在逻辑上,数据库有几层构造管理命名空间
  

   集簇->表空间tablespace->数据库database->模式schema
其中 模式是数据库内核中通过数据字典来区分,所从前三项都是通过存储架构的构造,来实现物理上的空间独立。
这在前面内核分析文章中也提到,表文件的定位,也是通过tablespace/database/relation三级来唯一标识。
  对于集簇这个概念,通过initdb创建的就是集簇,也就是数据存入的目录,在数据库服务启动时需要指定,它通常叫做PGDATA。
  数据文件

用户数据文件

   有表,索引,尚有对应的vm,fsm文件,都是按照命名空间的层级目录来存储
  事故干系数据

   由集簇级层级的空间管理,在集簇目录下有公共目录存放
  其它构造文件

   如表空间文件,数据字典文件,模版库,运行日记等文件,都是集簇层级的空间举行管理,在集簇目录下有各自的目录
  配置文件


   postgresql.conf
  
   pg_hba.conf和pg_ident.conf
  辅助文件

   如版本文件,运行信息文件等,都在PGDATA根目录下
  物理存储架构

     集簇文件结构

   先初始化一个全新的数据库集簇,下面初始化并启动数据库
  1. # 初始化postgres数据库集簇
  2. /opt/postgres/bin/initdb -D pgtest -W
  3. # 启动数据库,监听端口指定为 8888
  4. /opt/postgres/bin/pg_ctl -D pgtest -l logfile -o "-p 8888" start
  5. # 以命令行客户端,登陆数据库,指定端口和数据库
  6. /opt/postgres/bin/psql -p 8888 -d postgres
复制代码
  下面是initdb完成后,新建了一个表空间后的集簇目录结构,
然后为了看到一些文件类型,建了临时表,unlogged表,以及索引;
中心省略了一些表的文件列表,保存了目录层级和关键的文件。
  1. -- 表空间
  2. create tablespace tblspc_test location '/mnt/sda1/data/pgdata/pgtblspc';
  3. -- 普通表
  4. create table tbl_account(id integer, name varchar, address varchar, tel varchar);
  5. -- 临时表 会话退出后就会删除
  6. create temporary table tmptbl_test(id int, c_id int);
  7. -- unlogged 表,不会记录WAL,恢复时数据全部丢失
  8. create unlogged table unlogtbl_test(c_id int ,consumer varchar);
  9. create index on unlogtbl_test (c_id);
复制代码
  颠末上面的场景构造之后,现在来看一下数据库集簇下的文件和目录层次
  1. [senllang@hatch pgdata]$ tree pgtest
  2. pgtest
  3. ├── base
  4. │   ├── 1
  5. │   │   ├── 112
  6. │   │   ├── 113
  7. │   │   ├── 1247
  8. │   │   ├── 1247_fsm
  9. │   │   ├── 1247_vm
  10. │   │   ├── 1249
  11. ......
  12. │   │   ├── 827
  13. │   │   ├── 828
  14. │   │   ├── pg_filenode.map
  15. │   │   ├── pg_internal.init
  16. │   │   └── PG_VERSION
  17. │   ├── 4
  18. │   │   ├── 112
  19. │   │   ├── 113
  20. │   │   ├── 1247
  21. │   │   ├── 1247_fsm
  22. │   │   ├── 1247_vm
  23. ......
  24. │   │   ├── 6238
  25. │   │   ├── 6239
  26. │   │   ├── 826
  27. │   │   ├── 827
  28. │   │   ├── 828
  29. │   │   ├── pg_filenode.map
  30. │   │   └── PG_VERSION
  31. │   └── 5
  32. │       ├── 112
  33. │       ├── 113
  34. │       ├── 1247
  35. │       ├── 1247_fsm
  36. │       ├── 1247_vm
  37. │       ├── 16403
  38. │       ├── 16403_init
  39. │       ├── 16406
  40. │       ├── 16406_init
  41. │       ├── 16407
  42. │       ├── 16407_init
  43. │       ├── 16408
  44. │       ├── 16408_init
  45. │       ├── t3_16409
  46. │       └── t3_16412
  47. ......
  48. │       ├── 827
  49. │       ├── 828
  50. │       ├── pg_filenode.map
  51. │       ├── pg_internal.init
  52. │       └── PG_VERSION
  53. ├── global
  54. │   ├── 1213
  55. │   ├── 1213_fsm
  56. │   ├── 1213_vm
  57. │   ├── 1214
  58. │   ├── 1232
  59. │   ├── 1233
  60. │   ├── 1260
  61. │   ├── 1260_fsm
  62. │   ├── 1260_vm
  63. ......
  64. │   ├── pg_control
  65. │   ├── pg_filenode.map
  66. │   └── pg_internal.init
  67. ├── pg_commit_ts
  68. ├── pg_dynshmem
  69. ├── pg_hba.conf
  70. ├── pg_ident.conf
  71. ├── pg_logical
  72. │   ├── mappings
  73. │   ├── replorigin_checkpoint
  74. │   └── snapshots
  75. ├── pg_multixact
  76. │   ├── members
  77. │   │   └── 0000
  78. │   └── offsets
  79. │       └── 0000
  80. ├── pg_notify
  81. ├── pg_replslot
  82. ├── pg_serial
  83. ├── pg_snapshots
  84. ├── pg_stat
  85. ├── pg_stat_tmp
  86. ├── pg_subtrans
  87. │   └── 0000
  88. ├── pg_tblspc
  89. │   └── 16388 -> /mnt/sda1/data/pgdata/pgtblspc
  90. ├── pg_twophase
  91. ├── PG_VERSION
  92. ├── pg_wal
  93. │   ├── 000000010000000000000001
  94. │   └── archive_status
  95. ├── pg_xact
  96. │   └── 0000
  97. ├── postgresql.auto.conf
  98. ├── postgresql.conf
  99. ├── postmaster.opts
  100. └── postmaster.pid
复制代码
详细先容

文件/目录描述PG_VERSION一个包含PostgreSQL主版本号的文件base包含每个数据库对应的子目录的子目录current_logfiles记载当前被日记收集器写入的日记文件的文件global包含集簇范围的表的子目录,好比pg_databasepg_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(服务器关闭后该文件不存在) 表空间

   在表空间中创建了一个临时表,一个平常表,尚有一个数据库
  1. -- 创建数据库,指定存储的表空间
  2. create database test tablespace tblspc_test ;
  3. -- 在指定表空间创建临时表
  4. create temporary table tmptbl_test1(id int, c_id int) tablespace tblspc_test;
  5. -- 在指定表空间创建普通表
  6. create table tbl_salary(id integer, level float, performance float) tablespace tblspc_test;
复制代码
物理结构

   查看表空间目录中文件,目录层次和文件列表如下
  1. [senllang@hatch pgdata]$ tree pgtblspc/
  2. pgtblspc/
  3. └── PG_16_202306141
  4.     ├── 16389
  5.     │   ├── 112
  6.     │   ├── 113
  7.     │   ├── 1247
  8.     │   ├── 1247_fsm
  9.     │   ├── 1247_vm
  10.     │   ├── 1249
  11.     │   ├── 1249_fsm
  12.     │   ├── 1249_vm
  13.     ......
  14.     │   ├── 826
  15.     │   ├── 827
  16.     │   ├── 828
  17.     │   ├── pg_filenode.map
  18.     │   └── PG_VERSION
  19.     └── 5
  20.         ├── 16395
  21.         └── 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
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4