数据库集簇的逻辑结构
数据库集簇(database cluster)是指由单个PostgreSQL服务器实例管理的数据库集合。(解读:数据库集簇是集合,其元素是数据库。一个PostgreSQL服务器实例只会在单机上运行并管理单个数据库集簇。注意这里表述中的两个”单“,即单机单个集簇,说明服务器实例不能跨多个主机,不能管理多个数据库集簇)。数据库集簇在本质上就是一个文件目录,其包含着一些列子目录与文件。(例如执行/opt/pgsql/bin/initdb -D pgdata/10/data -W 在指定目录下创建基础目录,从而初始化一个新的数据库集簇,这里的/pgdata/10/data就是数据库集簇)基础目录文件树见文末。
注:PostgreSQL的数据库集簇(database cluster)概念和高可用数据库集群不同,这里的集簇(cluster)仅表示多个逻辑的数据库在用一个数据库实例中。
逻辑结构
区分数据库和数据库实例:PostgreSQL数据库是由一系列位于文件系统上的物理文件组成(通常这些物理文件被称为数据库);物理文件加上进程管理的内存和管理这些物理文件的进程称为该数据库的实例。在上述初始化数据目录的操作中,initdb工具自动创建了template0、template1和postgres数据库(解读:postgres是默认数据库,template0和template1是生成其他数据库的模板)。一个数据库集簇可以包含多个数据库、多个User,梅特数据库以及数据库中的表、索引等都有它们的拥有者:User。
创建一个Database时会为这个Database创建一个名为public的默认Schema,每个Database可以多个Schema,在数据库中创建表、索引等时如果没有指定Schema,都会在public这个Schema中。(解读:Schema可以理解为一个数据库中的命名空间,在数据库中创建的所有对象都在Schema中创建,一个用户可以从同一个客户端连接中访问不同的Schema)。不同的Schema中可以有多个相同名称的表、索引、视图等。
数据库对象
数据库是数据库对象(database object)的集合(例如,索引、视图、函数等都是数据库对象)。在PostgreSQL中,数据库本身也是数据库对象,并在逻辑上彼此分离。除数据库之外的其他数据库对象(如表、索引等)都归属于各自相应的数据库。虽然隶属于同一个数据库集簇,但无法直接从集簇中的一个数据库访问到。
表空间也是数据库对象,在PostgreSQL中最大的逻辑存储单元就是表空间。数据库中创建的对象,包括数据库本身都保存在表空间中(例如表、索引和整个数据库)。在创建数据库对象时,可以指定数据库对象的表空间,如果不指定则使用默认表空间。初始化数据库目录时会自动创建pg_default和pg_global两个表空间。
pg_global表空间的物理文件位置在数据目录的global目录中,它用来保存系统表。
pg_default表空间的物理文件位置在数据目录中的base目录,是template0和template1数据库的默认表空间。创建数据库时,默认从template1数据库进行克隆。因此除非特别指定新建数据库的表空间,默认使用template1的表空间。
在PostgreSQL内部,所有数据库对象都通过相应的对象标识符(object identifier, oid)进行管理,这些标识符是无符号的4字节整型。数据库对象和各个oid之间的关系存储在适当的系统目录中,具体取决于对象的类型。
数据库的oid存储在pg_database系统表中。
数据库中的表、索引、序列等对象的oid存储在pg_class系统表中。
从base文件目录下可以看到template0、template1和postgres对应的oid文件,也即相应的数据库文件。
pg_class系统表的oid为1259,它位于base目录postgres目录下,处于pg_default表空间中。
pg_database系统表的oid为1262,它位于global目录下,处于pg_global表空间中。
pg_default表空间的oid为1663,但是没有找到以1663命名的文件夹。
pg_global表空间的oid为1664,但是没有找到以1664命名的文件夹。
OID通常是从1开始分配,但在初始化数据集簇时,会先将一部分OID分配给系统表、系统表元祖、系统表上的索引等数据库对象,这一部分OID可以在系统表所对应的头文件中找到。同时,为了给后续版本留下扩展的余地,初始化数据集簇时还会预留一部分OID资源。这样,在系统运行时可分配的OID资源实际是从16384开始的。在PostgreSQL源代码src/include/catalog子目录下有一个shell脚本unused_oids用来输出当前版本中预分配和预留的OID的使用情况。
对于用户表的元祖,是可以在创建用户表时选择是否具有OID属性的。如果在CREATE TABLE语句中使用了WITH OIDS选项,则该用户表中插入的每一个元祖都将被分配一个OID。否则,默认状态下用户表的元祖是没有OID属性的。
OID的分配由系统中的一个全局OID计数器来实现,每次需要分配新的OID时,就从该计数器中取当前的OID,然后该计数器将会加1。OID分配时会采用互斥锁加以锁定以避免多个要求分配OID的请求获得同一个OID。
数据库的布局
如下图所示,一个数据库与base子目录下的一个子目录对应,且该子目录的名称与相应数据库的oid相同。例如,当数据库sampledb的oid为16384时,它对应的子目录名称就是16384。数据库中的每个表和索引都至少在相应子目录下存储为一个文件。
表空间的布局
PostgreSQL中的表空间对应一个包含基础目录之外数据的目录(附加数据区域)。执行CREATE TABLESPACE语句会在指定目录下创建表空间。在该目录下还会创建版本特定的子目录(PG_主版本号_目录版本号)。每个用户定义的表空间在PGDATA/pg_tblspc目录里面都有一个符号链接,它指向表空间的物理目录,该符号链接用表空间的OID命名。系统默认创建的表空间pg_default和pg_global并没有通过符号链接的方式指向其物理目录,而是直接对应PGDATA/base和PGDATA/global。
如果在mytblspc下创建新表,但新表所属的数据库却创建在基础目录下,那么PG会首先在版本特定的子目录下创建名称与现有数据库oid相同的新目录,然后将新表文件放置在刚创建的目录下。如下图Database Directory所指示的一样。
数据目录结构
/pgdata/10/data
|— PG_VERSION PostgreSQL主版本号文件
|— postgresql.conf 全局配置文件,除认证外其他行为由其配置
|— postgresql.auto.conf 只保存ALTER SYSTEM命令修改的参数
|— pg_hba.conf 全局配置文件,负责客户端的连接和认证配置
|— pg_ident.conf 控制PostgreSQL用户名映射
|— base
|--- 1 template1数据库目录
|--- 13213 template0数据库目录
|--- 13214 postgres数据库目录
|--- pg_twophase 用于预备事务状态文件的子目录
|--- pg_commit_ts 事务提交的时间戳数据
|--- pg_multixact 多事务状态数据
|--- pg_dynshmem 动态共享内存子系统中使用的文件
|--- pg_notify LISTEN/NOTIFY状态数据
|— pg_stat_tmp 统计子系统的临时文件
|— pg_wal WAL段文件,从pg_xlog重命名而来
|— pg_replslot 复制槽数据
|--- pg_subtrans 子事务状态数据
|— pg_xact 事务提交状态数据,从pg_clog重命名而来
数据库集簇的物理结构
每个表和索引都存储在其所属数据库目录下的独立文件里,以该表或者该索引的filenode号命名,该号码记录在该表或索引在系统表pg_class中对应元祖的relfilenode属性中。在表或索引超过1GB之后,它就被分裂成多个1GB大小的段。第一个段的文件名和filenode相同,随后的段命名为filemode.1,filenode.2 …这样的策略避免了在某些有文件大小限制的平台上可能出现的问题。如果一个表的有些属性要存储相当大的数据,那么就会有个与之相关联的TOAST表,用于存储无法在数据行中放置的超大外置数据。表对应的pg_class元祖的reltoastrelid属性记录了她的TOAST表OID。
表和元组的组织方式:在PG中,同一个表中的元组按照创建顺序依次插入到表文件中,元组之间不进行关联,这样的表文件称为堆文件。PG系统中包含了四种堆文件:普通堆(ordinary cataloged heap)、临时堆(temporary heap)、序列(SEQUENCE relation,一种特殊的单行表)和TOAST表(TOAST table)。临时堆的结构与普通堆相同,但临时堆仅在会话过程中临时创建,会话结束会自动删除。序列则是一种元组值自动增加的特殊堆。TOAST表其实也是一种普通堆,但是它被专门用于存储变长数据。尽管这几种堆文件功能各异,但在底层的文件结构却是相似的。每个堆文件都是由多个文件块组成。数据的读写是以块为单位,块默认大小为8K,在编译PG时指定的BLCKSZ决定块的大小。
文件块在物理磁盘上的存储形式如下。Page Header Data是长度为20字节的页头数据,包含该文件块的一般信息,如空闲空间的起始和结束位置、Special space的开始位置、项指针的开始位置、标志信息,如是否存在空闲项指针、是否所有的元组都可见。
Linp是ItemIdData类型的数组,ItemIdData类型由lp_off、lp_flags和lp_len三个属性组成。每个ItemIdDate结构用来指向文件块中的一个元组,其中lp_off是元组在文件块中的偏移量,而lp_len则说明了该元组的长度,lp_flags表示元组的状态(分为未使用、正常使用、HOT重定向和死亡四种状态)。每个Linp数组元素的长度为4字节。
Freespace是指未分配的空间(空闲空间),新插入页面中的元组及其对应的Linp元素都将从这部分空间中来分配,其中Linp元素从Freespace的开头开始分配,而新元组数据则从尾部开始分配。
Special space是特殊空间。用于存放与索引方法相关的特定数据,不同的索引方法在Special space中存放不同的数据。由于索引文件的文件块结构和普通表文件的相同,因此Special space在普通表文件块中并没有使用,其内容被置为空。
欢迎关注微信公众号肥叔菌PostgreSQL数据库专栏:
PostgreSQL数据库守护进程——Postmaster总体流程
PostgreSQL数据库守护进程——读取控制文件
PostgreSQL数据库守护进程——RemovePgTempFiles删除临时文件
PostgreSQL数据库守护进程——RemovePromoteSignalFiles
PostgreSQL数据库信号处理——kill backend
PostgreSQL数据库PMsignal——后端进程\Postmaster信号通信
PostgreSQL数据库后端进程——inter-process latch
PostgreSQL数据库后端进程——监视postmaster death
PostgreSQL数据库后台进程——一等公民
PostgreSQL数据库后台进程——后台一等公民进程保活
PostgreSQL数据库头胎——后台一等公民进程StartupDataBase启动
PostgreSQL数据库头胎——后台一等公民进程StartupDataBase信号通知
PostgreSQL数据库头胎——StarupXLOG函数恢复模式和目标
PostgreSQL数据库状态pmState——PM_STARTUP状态
PostgreSQL数据库复制——Setting Up Asynchronous Replication
PostgreSQL数据库复制——后台一等公民进程WalReceiver启动函数
PostgreSQL数据库复制——后台一等公民进程WalReceiver获知连接
PostgreSQL数据库复制——后台一等公民进程WalReceiver&startup交互
PostgreSQL数据库复制——后台一等公民进程WalReceiver ready_to_display
PostgreSQL数据库复制——后台一等公民进程WalReceiver提取信息
PostgreSQL数据库复制——后台一等公民进程WalReceiver收发逻辑
PostgreSQL数据库复制——后台一等公民进程WalReceiver pg_stat_wal_receiver视图
PostgreSQL数据库复制——walsender后端启动
PostgreSQL数据库守护进程——后台二等公民进程第一波启动maybe_start_bgworkers
PostgreSQL数据库参数——简述GUC
PostgreSQL数据库网络层——libpq连接参数
PostgreSQL数据库动态共享内存管理器——dynamic shared memory segment
PostgreSQL数据库WAL——资源管理器RMGR
PostgreSQL数据库WAL——备机回放checkpoint WAL
PostgreSQL数据库事务系统——phenomena
PostgreSQL数据库统计信息——analyze命令
PostgreSQL数据库统计信息——analyze大致流程
PostgreSQL数据库统计信息——analyze执行函数
PostgreSQL数据库统计信息——查找继承子表find_all_inheritors
PostgreSQL数据库统计信息——analyze流程对不同表的处理
PostgreSQL数据库统计信息——examine_attribute单列预分析
PostgreSQL数据库统计信息——acquire_sample_rows采样函数
PostgreSQL数据库统计信息——acquire_inherited_sample_rows采样函数
PostgreSQL数据库统计信息——计算统计数据
PostgreSQL数据库统计信息——compute_scalar_stats计算统计数
PostgreSQL数据库统计信息——analyze统计信息收集
PostgreSQL数据库统计信息——统计信息系统表
PostgreSQL守护进程(Postmaster)——辅助进程PgStat主流程
PostgreSQL守护进程(Postmaster)——辅助进程PgStat统计消息
PostgreSQL数据库查询监控技术——pg_stat_activity简介
PostgreSQL查询引擎——编译调试
PostgreSQL查询引擎——SELECT STATEMENTS
PostgreSQL查询引擎——Transform Values Clause
PostgreSQL查询引擎——Transform Select
PostgreSQL查询引擎——Transform Set Operation
PostgreSQL查询引擎——select * from where = transform流程
PostgreSQL查询引擎——Productions Expressions Grammar之columnref
PostgreSQL查询引擎——Transform Expressions之columnref
PostgreSQL查询引擎——Productions Expressions Grammar之CaseExpr
PostgreSQL查询引擎——Productions Expressions Grammar之AexprConst
PostgreSQL查询引擎——Transform Expressions之const
PostgreSQL查询引擎——Productions Expressions Grammar之GROUPING
PostgreSQL查询引擎——Restricted Expressions Grammar之表达式类型强转
PostgreSQL查询引擎——Transform Expressions之TypeCast
PostgreSQL查询引擎——Restricted Expressions Grammar之运算符
PostgreSQL查询引擎——SQL谓词表达式
PostgreSQL查询引擎——create table xxx(...)基础建表流程
PostgreSQL查询引擎——create table xxx(...)基础建表transformCreateStmt
PostgreSQL数据库查询执行——T_VariableSetStmt
PostgreSQL数据库查询执行——T_TransactionStmt
PostgreSQL数据库查询执行——Parallel Query
PostgreSQL数据库查询执行——SeqScan节点执行
PostgreSQL数据库查询执行——Using GDB To Trace Into a Parallel Worker Spawned By Postmaster During a Large Query
PostgreSQL数据库查询执行——Parallel SeqScan节点执行
PostgreSQL数据库可插拔存储引擎——pg_am系统表
PostgreSQL数据库可插拔存储引擎——Table Access Manager
PostgreSQL数据库可插拔存储引擎——GetTableAmRoutine函数
PostgreSQL数据库可插拔存储引擎——Table scan callbacks
PostgreSQL数据库HeapAM——TupleTableSlot类型
PostgreSQL数据库HeapAM——HeapAM Scan
PostgreSQL数据库HeapAM——HeapAM Parallel table scan
PostgreSQL数据库HeapAM——synchronized scan machinery
PostgreSQL数据库缓冲区管理器——概述
PostgreSQL数据库缓冲区管理器——本地缓冲区管理
PostgreSQL数据库缓冲区管理器——Shared Buffer Pool初始化
PostgreSQL数据库存储介质管理器——SMGR
PostgreSQL数据库存储介质管理器——磁盘管理器
PostgreSQL数据库目录——目录操作封装
PostgreSQL虚拟文件描述符VFD机制——FD LRU池
PostgreSQL虚拟文件描述符VFD机制——FD LRU池其他函数
PostgreSQL数据库FDW——The Internals of PostgreSQL
PostgreSQL数据库FDW——WIP PostgreSQL Sharding
PostgreSQL数据库FDW——Parquet S3 Foreign Data Wrapper
PostgreSQL数据库FDW——Parquet S3 ParquetReader类
PostgreSQL数据库FDW——Parquet S3 ReaderCacheEntry
PostgreSQL数据库FDW——Parquet S3 ParallelCoordinator
PostgreSQL数据库FDW——Parquet S3 DefaultParquetReader类
PostgreSQL数据库FDW——Parquet S3 CachingParquetReader类
PostgreSQL数据库FDW——Parquet S3 ParquetS3FdwExecutionState类
PostgreSQL数据库FDW——Parquet S3 MultifileMergeExecutionStateBaseS3类
PostgreSQL数据库FDW——Parquet S3 读取parquet文件用例
PostgreSQL数据库使用——between and以及日期的使用
PostgreSQL数据库使用——iRedMail定时备份数据库脚本
PostgreSQL数据库使用——iRedMail初始化数据库脚本
PostgreSQL数据库使用——iRedMail创建用户脚本
PostgreSQL数据库插件——定时任务pg_cron
PostgreSQL数据库故障分析——invalid byte sequence for encoding
ETCD、Zookeeper和Consul 分布式数据库的魔法银弹
PostgreSQL数据库高可用——patroni介绍[翻译]
PostgreSQL数据库高可用——patroni配置[翻译]
PostgreSQL数据库高可用——patroni REST API[翻译]
PostgreSQL数据库高可用——将独立集群转换为Patroni集群[翻译]
PostgreSQL数据库高可用——patroni源码学习
PostgreSQL数据库高可用——patroni源码学习——abstract_main
PostgreSQL数据库高可用——patroni源码AbstractPatroniDaemon类
PostgreSQL数据库高可用——patroni源码Patroni子类简介
PostgreSQL数据库高可用——patroni源码PatroniLogger类
PostgreSQL数据库高可用——patroni RestApiServer
PostgreSQL数据库高可用——patroni源码DCS类
PostgreSQL数据库高可用——patroni源码AbstractEtcd类
PostgreSQL数据库高可用——patroni源码EtcdClient类
PostgreSQL数据库高可用——patroni源码Etcd
PostgreSQL数据库高可用——patroni源码学习——Ha类概述
PostgreSQL数据库高可用——Patroni AsyncExecutor类
PostgreSQL数据库高可用——Patroni PostmasterProcess类
PostgreSQL数据库备份恢复迁移——Barman Before you start[翻译]
PostgreSQL数据库备份恢复迁移——Barman Introduction[翻译]
Postgres-XL数据库GTM——概念
Postgres-XL数据库GTM——事务管理
Postgres-XL数据库GTM——GTM and Global Transaction Management[翻译]
Postgres-XL数据库GTM——Master & Standby启动流程
Postgres-XL数据库GTM——Master & Standby子线程
Postgres-XL数据库GTM——Node管理器
Greenplum数据库统计信息——analyze命令 Greenplum数据库统计信息——分布式采样 Greenplum数据库统计信息——auto-analyze特性 Greenplum数据库Hash分布——计算哈希值和映射segment Greenplum数据库Hash分布——GUC gp_use_legacy_hashops Greenplum数据库数据分片策略Hash分布——执行器行为 Greenplum数据库过滤投影——ExecScan执行逻辑 Greenplum数据库外部表——Scan执行节点 Greenplum数据库外部表——fileam封装 Greenplum数据库外部表——external_getnext获取元组 Greenplum数据库外部表——url_curl创建销毁 Greenplum数据库外部协议——Define EXTPROTOCOL Greenplum数据库外部协议——GPHDFS实现协议 Greenplum数据库外部协议——GPHDFS gphdfs_fopen HashData数据库外部表——GPHDFS实现简介 Greenplum数据库高可用——FTS进程 Greenplum数据库高可用——FTS进程ftsConnect Greenplum数据库高可用——FTS进程触发轮询 Greenplum数据库高可用——FTS进程ftsPoll\Send\Receive Greenplum数据库高可用——FTS Pull模型 Greenplum数据库高可用——FTS HandleFtsWalRepProbe函数 Greenplum数据库高可用——FTS HandleFtsWalRepSyncRepOff函数 Greenplum数据库高可用——FTS HandleFtsWalRepPromote函数 Greenplum数据库高可用——FTS processRetry函数 Greenplum数据库高可用——FTS processResponse函数 Greenplum数据库高可用——FTS updateConfiguration更新系统表 Greenplum Python专用库gppylib学习——logging模块 Greenplum Python专用库gppylib学习——GpArray
Greenplum Python专用库gppylib学习——base.py
Greenplum Python工具库gpload学习——gpload类
Greenplum数据库源码分析——Standby Master操作工具分析
Greenplum数据库故障分析——利用GDB调试多线程core文件
Greenplum数据库故障分析——semop(id=,num=11) failed:invalid argument
Greenplum数据库故障分析——能对数据库base文件夹进行软连接嘛
Greenplum数据库故障分析——UDP Packet Lost(packet reassembles failed)
Greenplum数据库故障分析——版本升级后gpstart -a为何返回失败
Greenplum数据库故障分析——can not listen port
HAWQ数据库技术解析——内部架构
HAWQ数据库技术解析——filesystem interface
HAWQ数据库技术解析——HDFS filesystem
HAWQ数据库技术解析(一)——HAWQ简介[转载]