19.2. 创建数据库集群#
在执行任何操作之前,您必须在磁盘上初始化数据库存储区域。我们称之为数据库集群。(SQL标准使用术语目录集群。)数据库集群是单个正在运行的数据库服务器实例管理的数据库集合。初始化后,数据库集群将包含一个名为postgres
的数据库,它用作实用程序、用户和第三方应用程序使用的默认数据库。数据库服务器本身不要求存在postgres
数据库,但许多外部实用程序程序假定它存在。在初始化期间,每个集群中还会创建另外两个数据库,分别名为template1
和template0
。顾名思义,这些数据库将用作随后创建的数据库的模板;不应将它们用于实际工作。(有关在集群中创建新数据库的信息,请参见第 23 章。)
在文件系统术语中,数据库集群是一个存储所有数据的单个目录。我们称之为数据目录或数据区域。数据存储位置完全由您决定。没有默认位置,尽管/usr/local/pgsql/data
或/var/lib/pgsql/data
等位置很常见。在使用前必须使用随PostgreSQL一起安装的程序initdb初始化数据目录。
如果您使用的是PostgreSQL的预打包版本,它可能有一个特定约定,用于放置数据目录,它也可能提供一个用于创建数据目录的脚本。在这种情况下,您应该优先使用该脚本,而不是直接运行initdb
。有关详细信息,请参阅包级文档。
要手动初始化数据库集群,请运行initdb
并使用-D
选项指定数据库集群所需的文件系统位置,例如
$ initdb -D /usr/local/pgsql/data
请注意,您必须在登录到PostgreSQL用户帐户时执行此命令,该帐户在上一部分中进行了描述。
提示
作为-D
选项的替代方案,您可以设置环境变量PGDATA
。
或者,您可以通过pg_ctl程序运行initdb
如下所示
$ pg_ctl -D /usr/local/pgsql/data initdb
如果您使用pg_ctl
来启动和停止服务器(请参见第 19.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
身份验证或文件系统权限来限制连接。有关详细信息,请参阅第 21 章。)
initdb
还初始化数据库集群的默认区域设置。通常,它只会采用环境中的区域设置,并将其应用到已初始化的数据库。可以为数据库指定不同的区域设置;有关该内容的更多信息,请参阅第 24.1 节。initdb
设置在特定数据库集群中使用的默认排序顺序,虽然您可以使用不同的排序顺序创建新数据库,但 initdb 创建的模板数据库中使用的顺序无法更改,除非将其删除并重新创建。使用除C
或POSIX
之外的区域设置也会对性能产生影响。因此,第一次进行此选择时正确选择非常重要。
initdb
还设置数据库集群的默认字符集编码。通常应选择与区域设置匹配的编码。有关详细信息,请参阅第 24.3 节。
非C
和非POSIX
区域设置依赖于操作系统的排序库来进行字符集排序。这控制了存储在索引中的键的排序。因此,集群无法通过快照还原、二进制流复制、不同的操作系统或操作系统升级切换到不兼容的排序库版本。
19.2.1. 使用辅助文件系统#
许多安装会在除机器的“root”卷以外的文件系统(卷)上创建其数据库集群。如果您选择这样做,则不建议尝试将辅助卷的最顶层目录(装入点)用作数据目录。最佳做法是在装入点目录中创建一个由PostgreSQL用户拥有的目录,然后在其中创建数据目录。这避免了权限问题,特别是对于pg_upgrade等操作,并且如果辅助卷脱机,它还能确保干净的故障。
19.2.2. 文件系统#
通常,任何具有 POSIX 语义的文件系统都可以用于 PostgreSQL。用户出于各种原因(包括供应商支持、性能和熟悉度)而偏好不同的文件系统。经验表明,在其他所有条件相同的情况下,人们不应该仅仅因为切换文件系统或进行较小的文件系统配置更改而期望出现重大的性能或行为变化。
19.2.2.1. NFS#
可以将NFS文件系统用于存储PostgreSQL数据目录。PostgreSQL不会对NFS文件系统做任何特殊处理,这意味着它假定NFS的行为与本地连接的驱动器完全相同。PostgreSQL不会使用任何已知在NFS上具有非标准行为的功能,例如文件锁定。
使用NFS和PostgreSQL的唯一严格要求是使用hard
选项挂载文件系统。使用hard
选项时,如果出现网络问题,进程可能会无限期地““挂起””,因此此配置需要进行仔细的监控设置。soft
选项会在出现网络问题时中断系统调用,但PostgreSQL不会重复以这种方式中断的系统调用,因此任何此类中断都将导致报告 I/O 错误。
没有必要使用sync
挂载选项。async
选项的行为已足够,因为PostgreSQL会在适当的时候发出fsync
调用来刷新写入缓存。(这类似于它在本地文件系统上的工作方式。)但是,强烈建议在存在该选项的系统(主要是 Linux)上对 NFS服务器使用sync
导出选项。否则,NFS 客户端上的fsync
或等效操作实际上并不能保证到达服务器上的永久存储,这可能会导致类似于关闭参数fsync时运行的损坏。这些挂载和导出选项的默认值因供应商和版本而异,因此建议在任何情况下都检查并可能明确指定它们,以避免任何歧义。
在某些情况下,可以通过 NFS 或 iSCSI 等较低级别的协议访问外部存储产品。在后一种情况下,存储显示为块设备,可以在其上创建任何可用的文件系统。这种方法可能会减轻 DBA 处理 NFS 的某些特质的负担,但当然,管理远程存储的复杂性会出现在其他级别。