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