受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

18.2. 创建一个数据库集簇 #

在做任何事情之前,必须先在磁盘上初始化一个数据库存储区域。我们把它称为数据库集簇。(SQL 标准使用术语 catalog cluster。)数据库集簇是由一个正在运行的数据库服务器实例管理的一组数据库。初始化之后,数据库集簇中会包含一个名为postgres的数据库,作为供工具、用户和第三方应用使用的默认数据库。数据库服务器本身并不要求该postgres数据库存在,但许多外部工具程序都假定它存在。初始化期间,集簇中还会创建另一个数据库,名为template1。顾名思义,它会作为后续新建数据库的模板;不应将它用于实际工作。(关于在集簇中创建新数据库的信息,见Chapter 22。)

从文件系统角度看,数据库集簇就是一个单独的目录,所有数据都存放在其下。我们称之为数据目录数据区域。数据存放在哪里完全由你自己决定。虽然没有默认位置,但常见选择包括/usr/local/pgsql/data/var/lib/pgsql/data。在使用数据目录之前,必须先用随PostgreSQL安装的程序initdb对其进行初始化。

如果你使用的是预打包的 PostgreSQL,它很可能对数据目录的位置有固定约定,并且还可能提供创建数据目录的脚本。在这种情况下,应优先使用该脚本,而不是直接运行 initdb。详细信息请查阅该软件包级别的文档。

要手工初始化数据库集簇,请运行 initdb,并用 -D 选项指定数据库集簇所在的文件系统位置,例如:

$ initdb -D /usr/local/pgsql/data

请注意,执行该命令时必须已登录到上一节所述的 PostgreSQL 用户账户。

Tip

除了使用 -D 选项,也可以设置环境变量 PGDATA

或者,也可以通过pg_ctl程序运行initdb,如下所示:

$ pg_ctl -D /usr/local/pgsql/data initdb

如果你打算用pg_ctl来启动和停止服务器(见Section 18.3),这种方式可能更直观,因为这样pg_ctl就会成为你管理数据库服务器实例时使用的唯一命令。

如果指定的目录尚不存在,initdb会尝试创建它。当然,如果initdb对其父目录没有写权限,这会失败。通常建议让PostgreSQL用户不仅拥有数据目录,也拥有其父目录,这样就不会有这个问题。如果目标父目录也不存在,则需要先创建它;如果祖父目录不可写,就需要使用 root 权限。因此,过程可能如下所示:

root# mkdir /usr/local/pgsql
root# chown postgres /usr/local/pgsql
root# su postgres
postgres$ initdb -D /usr/local/pgsql/data

如果数据目录已存在且其中已有文件,initdb会拒绝运行;这是为了防止意外覆盖现有安装。

由于数据目录包含数据库中存储的全部数据,必须确保其不被未授权访问。因此,initdb会撤销除PostgreSQL用户之外其他人的访问权限,也可以选择保留组访问权限。启用组访问时仅为只读。这允许与集簇属主同组的非特权用户备份集簇数据,或执行其他只需要读权限的操作。

请注意,在现有集簇上启用或禁用组访问时,必须先关闭集簇,并在重新启动PostgreSQL前为所有目录和文件设置正确的权限模式。否则,数据目录中可能会混杂多种权限模式。对于只允许属主访问的集簇,适当的模式是目录为0700、文件为0600。对于还允许同组用户读取的集簇,适当的模式是目录为0750、文件为0640

不过,尽管目录内容是安全的,默认的客户端认证设置却允许任何本地用户连接到数据库,甚至成为数据库超级用户。如果你不信任其他本地用户,我们建议在运行initdb时使用-W--pwprompt--pwfile之一,为数据库超级用户指定密码。 另外,指定-A scram-sha-256,以避免使用默认的trust认证方式;或者在运行initdb之后、首次启动服务器之前修改生成的pg_hba.conf文件。(其他合理方法包括使用peer认证,或使用文件系统权限限制连接。更多信息见Chapter 20。)

initdb还会为数据库集簇初始化默认区域设置。通常,它只是采用环境中的区域设置,并将其应用到新初始化的数据库。你也可以为数据库指定不同的区域设置;更多信息见Section 23.1。该数据库集簇内部使用的默认排序顺序由initdb设定。虽然你可以创建采用不同排序顺序的新数据库,但initdb创建的模板数据库所使用的排序顺序,若不删除并重建它们就无法更改。使用非CPOSIX区域设置还会带来性能影响,因此第一次就做出正确选择很重要。

initdb还会为数据库集簇设置默认字符集编码。通常应选择与区域设置相匹配的字符集编码。详见Section 23.3

C和非POSIX的区域设置依赖操作系统的排序规则库来决定字符集排序。这会控制索引中存储键值的顺序。因此,无论是通过快照恢复、二进制流复制、切换到不同操作系统,还是升级操作系统,都不能让一个集簇切换到不兼容版本的排序规则库。

18.2.1. 二级文件系统的使用 #

很多安装会把数据库集簇建在机器卷以外的文件系统(卷)上。如果这样做,不建议把二级卷的最顶层目录(挂载点)直接用作数据目录。最佳实践是在挂载点目录下创建一个由PostgreSQL用户拥有的目录,再在其下创建数据目录。这样可以避免权限问题,尤其是在执行pg_upgrade之类的操作时;同时也能确保二级卷脱机时以干净的方式失败。

18.2.2. 文件系统 #

一般来说,任何具有 POSIX 语义的文件系统都可用于 PostgreSQL。用户偏好不同文件系统的原因多种多样,包括厂商支持、性能以及熟悉程度等。经验表明,在其他条件相同的情况下,不应期望仅仅通过切换文件系统或做一些小幅文件系统配置调整,就出现显著的性能或行为变化。

18.2.2.1. NFS #

可以使用 NFS 文件系统存放 PostgreSQL 数据目录。PostgreSQL不会对NFS文件系统作任何特殊处理,这意味着它假定NFS的行为与本地直连磁盘完全一致。PostgreSQL也不会使用任何已知在NFS上行为不标准的功能,例如文件锁定。

对于在PostgreSQL中使用NFS,唯一硬性要求是文件系统必须使用hard选项挂载。使用hard选项时,如果出现网络问题,进程可能会无限期地挂起,因此这种配置需要配套谨慎的监控措施。soft选项会在网络问题出现时中断系统调用,但PostgreSQL不会重试以这种方式被中断的系统调用,因此任何此类中断都会导致报告 I/O 错误。

没有必要使用sync挂载选项。async选项的行为已经足够,因为PostgreSQL会在适当的时候发出fsync调用来刷新写缓存。(这和它在本地文件系统上的工作方式类似。)但是,强烈建议在支持该选项的NFS服务器端系统上使用sync导出选项(主要是 Linux)。否则,NFS 客户端上的fsync或等效操作实际上并不能保证数据到达服务器上的持久存储,这可能导致类似于将参数fsync设为关闭时那样的损坏。这些挂载和导出选项的默认值在不同厂商和版本间并不相同,因此无论如何都建议检查它们,并且最好显式指定,以避免歧义。

在某些情况下,可以通过 NFS 或更底层的协议(例如 iSCSI)访问外部存储产品。在后一种情况下,存储会表现为块设备,可以在其上创建任意可用的文件系统。这种方式或许能让 DBA 不必应对 NFS 的某些特性,但当然,管理远程存储的复杂性会转移到其他层面。

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。