Skip to content

PostgreSQL 数据库集群创建指南 ​

概述 ​

在使用 PostgreSQL 之前,必须在磁盘上初始化一个数据库存储区域,我们称之为数据库集群。数据库集群是由单个 PostgreSQL 服务器实例管理的数据库集合,它解决了数据存储和组织管理的核心问题。

INFO

术语说明 SQL 标准使用术语"目录集群",但 PostgreSQL 社区通常称之为"数据库集群"。

数据库集群的核心概念 ​

什么是数据库集群 ​

数据库集群本质上是一个文件系统目录,包含:

  • postgres 数据库:默认数据库,供实用程序、用户和第三方应用程序使用
  • template1 数据库:用作创建新数据库的模板
  • template0 数据库:原始模板,不应修改

业务场景应用 ​

在实际业务中,数据库集群的设计解决了以下问题:

  1. 多租户应用:每个租户可以拥有独立的数据库,但共享同一个服务器实例
  2. 开发环境隔离:开发、测试、生产环境可以使用不同的数据库
  3. 业务模块分离:用户管理、订单系统、库存管理可以使用不同的数据库

数据目录选择与规划 ​

推荐的目录位置 ​

环境类型推荐路径说明
生产环境/var/lib/pgsql/data标准生产环境路径
开发环境/usr/local/pgsql/data开发测试环境
自定义环境/data/postgresql/独立磁盘挂载点

数据目录的选择对性能和可维护性有重要影响,建议选择独立的磁盘分区。

初始化数据库集群 ​

方法一:使用 initdb 命令 ​

基本语法 ​

bash
# 基本初始化命令
initdb -D /usr/local/pgsql/data

# 使用环境变量方式
export PGDATA=/usr/local/pgsql/data
initdb

完整的初始化示例 ​

问题场景:为新的 PostgreSQL 服务器创建生产环境的数据库集群

解决方案:

bash
# 1. 创建必要的目录结构(需要 root 权限)
sudo mkdir -p /usr/local/pgsql
sudo chown postgres:postgres /usr/local/pgsql

# 2. 切换到 postgres 用户
sudo su - postgres

# 3. 初始化数据库集群
initdb -D /usr/local/pgsql/data \
       --encoding=UTF8 \
       --locale=zh_CN.UTF-8 \
       --data-checksums \
       -W

参数说明:

  • -D:指定数据目录位置
  • --encoding=UTF8:设置字符编码
  • --locale=zh_CN.UTF-8:设置区域设置
  • --data-checksums:启用数据校验和
  • -W:提示设置超级用户密码

预期输出:

The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "zh_CN.UTF-8".
The default database encoding has accordingly been set to "UTF8".

Data page checksums are enabled.

creating directory /usr/local/pgsql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Asia/Shanghai
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

Success. You can now start the database server using:

    pg_ctl -D /usr/local/pgsql/data -l logfile start

方法二:使用 pg_ctl 程序 ​

bash
# 使用 pg_ctl 初始化
pg_ctl -D /usr/local/pgsql/data initdb

TIP

建议如果计划使用 pg_ctl 来启动和停止服务器,建议也使用它来初始化,保持工具的一致性。

权限和安全配置 ​

文件系统权限 ​

初始化完成后,PostgreSQL 会自动设置适当的文件权限:

访问类型目录权限文件权限适用场景
仅所有者07000600高安全性环境
组读取07500640允许备份用户访问
bash
# 检查权限设置
ls -la /usr/local/pgsql/data/
# drwx------ 19 postgres postgres 4096 Jun  5 10:30 .

身份验证配置 ​

默认配置的安全风险:默认情况下,PostgreSQL 允许任何本地用户连接并成为超级用户,这在生产环境中是不安全的。

安全加固方案:

bash
# 1. 初始化时设置超级用户密码
initdb -D /usr/local/pgsql/data -W -A scram-sha-256

# 2. 或在初始化后修改认证方法
# 编辑 pg_hba.conf 文件
vim /usr/local/pgsql/data/pg_hba.conf

pg_hba.conf 安全配置示例:

sql
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# 本地连接使用密码认证
local   all             all                                     scram-sha-256

# IPv4 本地连接
host    all             all             127.0.0.1/32            scram-sha-256

# IPv6 本地连接
host    all             all             ::1/128                 scram-sha-256

# 生产环境远程连接(限制特定 IP)
host    all             all             192.168.1.0/24          scram-sha-256

区域设置和字符编码 ​

区域设置的重要性 ​

区域设置影响:

  • 排序规则:影响 ORDER BY 和索引的行为
  • 字符分类:影响大小写转换和模式匹配
  • 数字和日期格式:影响数据的显示格式

WARNING

注意区域设置一旦确定,就无法在不重建集群的情况下更改。因此,初始选择非常重要。

字符编码选择 ​

bash
# 查看系统支持的编码
initdb --help | grep -A 20 "encoding"

# 常用编码选择
initdb -D /usr/local/pgsql/data --encoding=UTF8    # 通用选择
initdb -D /usr/local/pgsql/data --encoding=SQL_ASCII  # 仅英文环境

高级存储配置 ​

二级文件系统使用 ​

业务场景:生产环境中通常将数据库数据存储在独立的磁盘分区上,以提高性能和可靠性。

最佳实践:

bash
# 1. 挂载独立存储设备
sudo mount /dev/sdb1 /data

# 2. 在挂载点下创建专用目录
sudo mkdir /data/postgresql
sudo chown postgres:postgres /data/postgresql

# 3. 在专用目录中初始化集群
sudo su - postgres
initdb -D /data/postgresql/data

TIP

最佳实践不要直接使用挂载点作为数据目录,而应在挂载点下创建子目录。这样可以避免权限问题,并确保在存储设备离线时能够优雅地处理失败。

NFS 存储配置 ​

使用场景:在云环境或共享存储架构中,可能需要将 PostgreSQL 数据存储在 NFS 文件系统上。

必要配置:

bash
# 1. 使用 hard 选项挂载(必须)
mount -t nfs -o hard,intr nfs-server:/export/pgsql /data/pgsql

# 2. 验证挂载选项
mount | grep pgsql
# nfs-server:/export/pgsql on /data/pgsql type nfs (rw,hard,intr)

NFS 服务器端配置:

bash
# /etc/exports 配置示例
/export/pgsql    192.168.1.0/24(rw,sync,no_subtree_check)
选项说明重要性
hard网络问题时挂起而非失败必须
sync同步写入(服务器端)强烈推荐
intr允许中断挂起的调用推荐

常见问题和故障排除 ​

权限问题 ​

问题现象:

bash
initdb: could not create directory "/usr/local/pgsql": Permission denied

解决方案:

bash
# 1. 检查父目录权限
ls -ld /usr/local/

# 2. 使用 root 权限创建目录
sudo mkdir -p /usr/local/pgsql
sudo chown postgres:postgres /usr/local/pgsql

# 3. 切换到 postgres 用户重新初始化
sudo su - postgres
initdb -D /usr/local/pgsql/data

目录已存在 ​

问题现象:

bash
initdb: directory "/usr/local/pgsql/data" exists but is not empty

解决方案:

bash
# 1. 检查目录内容
ls -la /usr/local/pgsql/data/

# 2. 如果确认可以删除
rm -rf /usr/local/pgsql/data/*

# 3. 或选择新的目录
initdb -D /usr/local/pgsql/data-new

编码不匹配 ​

问题现象:

bash
initdb: encoding mismatch

解决方案:

bash
# 1. 检查系统区域设置
locale

# 2. 明确指定编码和区域
initdb -D /usr/local/pgsql/data \
       --encoding=UTF8 \
       --lc-collate=C \
       --lc-ctype=C

初始化后的验证 ​

验证集群状态 ​

bash
# 1. 检查数据目录结构
ls -la /usr/local/pgsql/data/
# 应该看到 postgresql.conf, pg_hba.conf 等配置文件

# 2. 启动数据库服务器
pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/server.log start

# 3. 连接到数据库
psql -h localhost -U postgres

检查默认数据库 ​

sql
-- 连接后查看数据库列表
\l

-- 应该看到以下数据库:
-- postgres  | postgres | UTF8     | ...
-- template0 | postgres | UTF8     | ...
-- template1 | postgres | UTF8     | ...

总结 ​

PostgreSQL 数据库集群的创建是数据库管理的第一步,正确的初始化配置对后续的性能、安全性和可维护性都有重要影响。关键要点包括:

  1. 合理选择数据目录位置,考虑性能和可维护性
  2. 正确设置权限和安全配置,特别是身份验证方法
  3. 谨慎选择区域设置和字符编码,避免后期重建集群
  4. 对于生产环境,考虑使用独立存储和适当的文件系统

通过遵循这些最佳实践,可以为 PostgreSQL 数据库建立一个稳定、安全、高性能的基础环境。