打算在刚开始的时候参考《Postgresql数据库内核分析》和PG的文档来学习。先了解了一下安装和启动pg之后,pg会在一台机器上创建那些文件和目录。
【引用请注明出处:http://www.jb51.cc/article/p-oqmktubt-mv.html】
1。PG的C/S架构
了解目录和文件之前,先看了一下pg的架构。pg采用的是常见的C/S架构,服务器端叫做postgres(服务器端的主程序和进程都叫这个名字,启动pg之后在服务器上至少可以看到6个postgres进程,对应于pg的几个主要的模块,并且每增加一个客户端连接,服务器段就会增加一个postgres进程来和客户端交互),管理所有的数据文件、接受客户端的连接、执行客户端提交的操作。客户端则可以是JDBC/ODBC、psql命令行客户端、嵌入式sql客户端等等。
2. PG的目录与文件
pg的目录结构很清晰,一个是安装目录,默认在/usr/local/pgsql下。另外一个就是存放数据文件和配置文件的目录,文档中叫做cluster's data directory,内核分析中译作数据集簇。数据集簇通常叫做PGDATA。每个数据库实例都会有一个PGDATA,每台机器上可以并存多个不同的实例。
2.1. PGDATA下的文件
PGDATA下各个文件和子目录的作用详见PG9.3文档58章。其中的postgresql.conf、pg_hba.conf、pg_ident.conf是pg的配置文件,也就是说每个pg实例都有自己的配置,愚以为这一点上MysqL和pg很像。这3个配置文件中,pg_hba.conf配置了pg的访问权限,限制了哪些机器/IP段上的哪些用户对pg有什么样的访问权限,默认配置中只有本地用户可以访问pg。pg_ident.conf定义了操作系统用户名和pg中用户名的映射关系。postgresql.conf中包含了一个pg实例的其他所有配置。postmaster.pid文件是一个锁文件,生命周期和postmaster(pg最主要的一个进程,操作系统中其进程名也是postgres)进程一样,其中记录了postmaster的pid和共享内存段id。postmaster.opts中记录了postmaster上一次启动时的命令行参数。
2.2. PGDATA下的目录
PGDATA下的目录,最基本的是base和global。base中放了每个数据的文件,每个数据库会在base目录下有一个以该数据库oid(object id,pg具有面向对象数据库的一些特性,其中的数据库、视图、数据表,甚至某些元组都被作为数据对象管理,每个数据对象有一个唯一oid)命名的子目录。其中命名为1的子目录是pg中的模板数据库template1,pg中的数据库都会以template1作为模板,也就是说template1中的内容会被复制到所有的数据库中。global目录下存放了该实例的共享系统表,如pg_database(存放该实例中所有数据库的元信息)。
3. PG的系统表与系统视图
说到pg的系统表和系统视图,也就是pg的数据字典,是pg的核心,查询编译、存储管理、事务管理、日志管理都要依赖数据字典中的元数据。pg中每一个数据库都会有自己的系统表和系统视图。可以说没有系统表就没法执行sql操作、没法create table。可是系统表/系统试图在pg,包括其他很多DBMS中,都是以普通的数据表/视图形式存在和管理的,这就存在一个鸡生蛋蛋生鸡的问题。在pg的源码src/backend/catalog/genbki.pl中包含了相关的脚本。在编译pg时,会执行这个脚本、生成一个postgres.bki文件(默认在/usr/local/pgsql/share目录下)。BKI(backend interface)是pg内部的一种特殊脚本,在执行initdb时,pg的后端(无需经过SQL查询编译)可以处理这种脚本、以bootstrap模式执行。在bootstrap模式下,可以从零开始创建数据库模板template1、创建系统视图、系统表、template0和postgres数据库。
template0和postgres数据库都是从template1创建的,这3个都是pg的系统数据库,其中template1在initdb完成之后是可以由用户修改的,template0则始终提供一个未被修改的干净模板。postgres数据库提供一个初始的可供用户连接的数据库。
具体的BKI与系统表的内容,分别参考PG文档59章
4. 数据库中的文件
每个数据库在PGDATA/base目录下都有一个以该数据库oid命名的子目录,该数据库的所有文件、包括系统表默认都在这个目录下(也有例外)。数据库中的每张数据表的索引和数据都存放同一个文件中。数据表文件以该数据表的filenode号命名。filenode在pg_class系统表的relfilenode属性中可以看到。每张表除了存放数据和索引的文件外,还会有一个_fsm文件(free space map),其中存放了数据表文件中空闲空间的信息,还有一个_vm文件(visibility map),标记了数据表文件中哪些文件块没有失效的元组(pg采用的典型的行存储策略,每个元组都连续地存放在一起,一个数据块中常常存放多个元组,每个块的块头有slot array标记了每个元组的偏移量)。
对于数据表文件,pg采取段页式管理方式,每个段的默认大小是1GB。每个段都是一个文件,也就是说,默认配置下,pg中的一个数据表超过1GB时会分为多个1GB大小的文件,第一个段文件名依然是filenode number,第二个段文件是filenode number.1,依此类推。
对于数据表中的大对象,pg会将其存放在另外的一个TOAST表中,因为大对象不适合与其他属性一起按行存放在段页中。
参考文献:
《内核分析》2.2节
PG9.3文档58、59章
原文链接:https://www.f2er.com/postgresql/196049.html