
前言
本文记录一套基于 AlmaLinux 9 + PostgreSQL 18.4 的 PostgreSQL 一主一备 Streaming Replication 部署流程。
本次数据库并非手工安装,而是使用自动化部署脚本一键部署:
PgShellInstall v4.2.1-pro
完成 PostgreSQL 源码编译安装、数据库初始化、Primary/Standby 配置、复制用户创建、Replication Slot、WAL 归档以及 Streaming Replication 主备搭建。
文中涉及的 PgShellInstall 自动化部署脚本未公开附录,如有相关使用需求,可留言交流。
需要强调的是:
自动化脚本负责快速完成基础部署,DBA 仍需要完成生产标准化检查、备份目录调整、安全收敛以及最终验收。
本文按照实际生产部署逻辑整理,后续遇到类似 PostgreSQL 主备部署场景,只需替换:
IP
Hostname
SSH端口
PostgreSQL版本
服务器资源
业务网段
密码
即可快速复用。
本文使用的 PgShellInstall 4.2.1-pro 当前存在两个需要特别注意的点:
1. 当前没有 –backup-dir 参数
2. 自动生成的备份/WAL清理脚本部分路径为固定默认值
因此部署完成后需要进行一次目录标准化。PostgreSQL18_Streaming_Replicat…
一、整体架构
本文采用 PostgreSQL 标准一主一备物理流复制架构。
Application
|
TCP / 5432
|
v
+———————-+
| PostgreSQL Primary |
| 192.168.10.101 |
| pg-primary.example |
+———-+———–+
|
WAL Streaming
|
v
+———————-+
| PostgreSQL Standby |
| 192.168.10.102 |
| pg-standby.example |
+———————-+
架构参数:
| PostgreSQL | 18.4 |
| OS | AlmaLinux 9.x |
| 架构 | Primary + Physical Standby |
| 复制方式 | Streaming Replication |
| 复制模式 | ASYNC |
| 数据库端口 | 5432 |
| 认证 | SCRAM-SHA-256 |
| WAL Level | replica |
| 时区 | Asia/Shanghai |
标准目录:
/app/pgsql PostgreSQL软件
/app/pgdata PostgreSQL数据
/app/pgarchive WAL归档
/app/pgbackup 数据库备份
/app/pgcheck 数据库巡检
/soft 安装包和部署脚本
二、环境规划
示例服务器:
| IP | 192.168.10.101 | 192.168.10.102 |
| Hostname | pg-primary.example | pg-standby.example |
| CPU | 8C | 8C |
| Memory | 16GB | 16GB |
| 数据盘 | /app | /app |
| PostgreSQL | 18.4 | 18.4 |
| PostgreSQL Port | 5432 | 5432 |
| SSH Port | 62222 | 62222 |
生产原则:
主备版本一致
目录规划一致
时间同步正常
主备网络互通
/app 使用独立数据盘
5432 未被其他进程占用
三、部署前系统检查
主备两台均执行:
hostname -f
cat /etc/os-release
uname -r
lscpu | egrep 'CPU\\(s\\)|Model name'
free -h
df -h
timedatectl
chronyc tracking 2>/dev/null || true
getenforce
systemctl is-active firewalld
ss -lntp | grep ':5432 ' || echo "5432未占用"
重点确认:
操作系统版本正确
/app 已挂载
磁盘容量正常
CPU/内存符合规划
系统时间同步
5432端口未占用
四、配置 Hosts
Primary、Standby 两台都配置:
cat >> /etc/hosts <<'EOF'
192.168.10.101 pg-primary.example
192.168.10.102 pg-standby.example
EOF
检查:
getent ahostsv4 pg-primary.example
getent ahostsv4 pg-standby.example
网络测试:
ping -c 3 pg-primary.example
ping -c 3 pg-standby.example
要求双方均能正确解析和互通。该步骤也是本次 SOP 中固定的部署前置流程。PostgreSQL18_Streaming_Replicat…
五、时间同步
设置时区:
timedatectl set-timezone Asia/Shanghai
启用 Chrony:
systemctl enable –now chronyd
检查:
timedatectl
chronyc tracking
chronyc sources -v
应重点确认:
Time zone = Asia/Shanghai
NTP service = active
System clock synchronized = yes
企业环境应使用内部 NTP Server。
六、防火墙及网络
生产环境不建议为了部署数据库直接关闭防火墙。
推荐按照最小权限开放。
例如允许业务网段访问 PostgreSQL:
firewall-cmd –permanent \\
–add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="5432" protocol="tcp" accept'
允许主库访问备库部署 SSH 端口:
firewall-cmd –permanent \\
–add-rich-rule='rule family="ipv4" source address="192.168.10.101/32" port port="62222" protocol="tcp" accept'
重新加载:
firewall-cmd –reload
firewall-cmd –list-all
从 Primary 测试 Standby:
ssh -p 62222 root@192.168.10.102 'hostname -f'
七、准备 YUM / DNF 软件源
PostgreSQL 本次采用源码安装,但编译依赖仍然需要操作系统 Repository。
优先使用:
企业内部YUM仓库
或
系统ISO本地仓库
检查:
dnf repolist
如果服务器完全离线,可挂载系统 ISO:
mkdir -p /mnt
mount /dev/sr0 /mnt
检查:
ls /mnt/BaseOS
ls /mnt/AppStream
本地 Repository 示例:
[LocalRepo-BaseOS]
name=AlmaLinux-Local-BaseOS
baseurl=file:///mnt/BaseOS/
enabled=1
gpgcheck=0
[LocalRepo-AppStream]
name=AlmaLinux-Local-AppStream
baseurl=file:///mnt/AppStream/
enabled=1
gpgcheck=0
刷新:
dnf clean all
dnf makecache
dnf repolist
八、安装 PostgreSQL 编译依赖
主备两台都执行。
dnf install -y \\
gcc gcc-c++ make perl bzip2 pkgconf-pkg-config \\
readline-devel zlib-devel openssl-devel \\
libxml2-devel libxslt-devel pam-devel \\
libicu-devel openldap-devel bison flex expect
检查:
rpm -q \\
gcc gcc-c++ make perl bzip2 pkgconf-pkg-config \\
readline-devel zlib-devel openssl-devel \\
libxml2-devel libxslt-devel pam-devel \\
libicu-devel openldap-devel bison flex expect
这组依赖已经在 PostgreSQL 18.4 源码部署过程中实际验证。PostgreSQL18_Streaming_Replicat…
三个常见报错需要记住。
缺少 bzip2:
.tar.bz2 无法正常检查/解压
处理:
dnf install -y bzip2
缺少 ICU:
Package 'icu-uc' not found
Package 'icu-i18n' not found
处理:
dnf install -y libicu-devel
缺少 Bison:
bison not found
处理:
dnf install -y bison flex
九、下载 PostgreSQL 源码包
PostgreSQL 官方源码:
https://ftp.postgresql.org/pub/source/
PostgreSQL 18.4:
https://ftp.postgresql.org/pub/source/v18.4/postgresql-18.4.tar.bz2
有互联网环境可以:
wget https://ftp.postgresql.org/pub/source/v18.4/postgresql-18.4.tar.bz2
生产内网通常下载后再通过堡垒机上传。
统一放:
mkdir -p /soft
最终:
/soft/PgShellInstall
/soft/postgresql-18.4.tar.bz2
十、校验源码包
tar -tjf /soft/postgresql-18.4.tar.bz2 >/dev/null && \\
echo "PostgreSQL 18.4安装包检查正常"
如果这里失败,不要继续安装。
十一、准备 PgShellInstall
cd /soft
chmod +x PgShellInstall
查看:
./PgShellInstall –help
本文经过验证的版本:
PgShellInstall v4.2.1-pro
后续如果脚本版本变化,正式执行前应重新查看 –help,不要默认所有参数永久不变。
十二、执行 PostgreSQL 主备自动化部署
从 Primary 的 root 用户执行。
示例:
cd /soft
./PgShellInstall \\
–mode streaming \\
–pg-version 18 \\
–port 5432 \\
–datadir /app/pgdata \\
–install-dir /app/pgsql \\
–locale en_US.UTF-8 \\
–password '<POSTGRES_PASSWORD>' \\
–auth-method scram-sha-256 \\
–max-connections 300 \\
–allowed-networks 192.168.10.0/24 \\
–enable-archiving on \\
–wal-level replica \\
–huge-pages try \\
-opd Y \\
–timezone Asia/Shanghai \\
–archive-dir /app/pgarchive \\
–primary-host 192.168.10.101 \\
–standby-hosts 192.168.10.102 \\
–repl-user replicator \\
–repl-password '<REPLICATION_PASSWORD>' \\
–synchronous-commit off \\
–max-wal-senders 20 \\
–sync-method first \\
–sync-count 1 \\
–ssh-user root \\
–ssh-password '<STANDBY_ROOT_PASSWORD>' \\
–ssh-port 62222
本文当前脚本已经支持主库、备库、归档目录、复制用户等参数。PostgreSQL18_Streaming_Replicat…
三个重要说明
1. 不要机械使用 max_connections=2000
连接数必须结合:
服务器内存
应用连接池
业务并发
work_mem
后台进程
综合计算。
16GB 级别主机可先从几百连接规划。
2. 生产不要使用
0.0.0.0/0
作为长期数据库访问范围。
应填写实际:
应用网段
管理网段
备库IP
3. 当前版本不要写
–repo-mode auto
本次验证中该值不被当前脚本识别。
十三、部署完成后检查版本和服务
主备分别执行:
/app/pgsql/bin/postgres –version
例如:
postgres (PostgreSQL) 18.4
服务:
systemctl status postgresql-18 –no-pager
检查自启动:
systemctl is-enabled postgresql-18
检查端口:
ss -lntp | grep ':5432 '
正常要求:
PostgreSQL版本正确
service active(running)
service enabled
5432正常监听
十四、确认 Primary 状态
Primary:
su – postgres
执行:
psql -c "select pg_is_in_recovery();"
正常:
f
代表当前节点是 Primary。
十五、检查 Primary → Standby 复制
Primary:
psql -c "select client_addr,state,sync_state,pg_wal_lsn_diff(sent_lsn,replay_lsn) as lag_bytes from pg_stat_replication;"
正常示例:
client_addr | state | sync_state | lag_bytes
—————-+———–+————+———–
192.168.10.102 | streaming | async | 0
判断标准:
state = streaming
本文使用:
sync_state = async
因此看到 async 属于正常。
十六、确认 Standby 状态
Standby:
su – postgres
执行:
psql -c "select pg_is_in_recovery(); select status,sender_host,sender_port from pg_stat_wal_receiver;"
正常应看到:
pg_is_in_recovery = t
status = streaming
sender_host = 192.168.10.101
sender_port = 5432
此时说明:
Standby处于Recovery状态
+
WAL Receiver连接Primary
+
Streaming Replication正常
十七、日常最简主备巡检
以后日常其实重点记住这两条即可。
Primary
psql -c "select client_addr,state,sync_state,pg_wal_lsn_diff(sent_lsn,replay_lsn) as lag_bytes from pg_stat_replication;"
Standby
psql -c "select status,sender_host,sender_port from pg_stat_wal_receiver;"
看到:
Primary state = streaming
Standby status = streaming
并且复制延迟正常,即可快速判断主备链路。
十八、检查 Replication Slot
Primary:
psql -c "select slot_name,slot_type,active,restart_lsn from pg_replication_slots;"
正常应看到物理复制槽,例如:
standby_slot_1
并且:
active = t
需要注意:
Replication Slot 可以保护备库所需 WAL,但如果 Standby 长时间宕机,也可能导致 Primary WAL 无法回收并持续增长。
生产环境必须监控:
pg_wal
Replication Slot
Standby状态
磁盘空间
十九、检查 WAL Archive
Primary:
psql -c "show archive_mode;"
正常:
on
检查:
psql -c "show archive_command;"
归档目录:
/app/pgarchive
查看:
ls -lh /app/pgarchive
查询归档状态:
psql -c "select archived_count,last_archived_wal,last_archived_time,failed_count,last_failed_wal,last_failed_time from pg_stat_archiver;"
重点:
failed_count = 0
二十、修正自动备份目录
这一部分是 PgShellInstall 4.2.1-pro 当前版本必须关注的生产化收尾项。
当前脚本生成的备份目录默认是:
/var/lib/pgsql/backup
每日:
/var/lib/pgsql/backup/daily
每周:
/var/lib/pgsql/backup/weekly
脚本当前没有 –backup-dir 参数。PostgreSQL18_Streaming_Replicat…
如果 /var 位于根盘,大数据库长期运行有将根文件系统写满的风险。
推荐统一调整到:
/app/pgbackup
创建:
mkdir -p \\
/app/pgbackup/daily \\
/app/pgbackup/weekly
chown -R postgres:postgres /app/pgbackup
chmod 700 \\
/app/pgbackup \\
/app/pgbackup/daily \\
/app/pgbackup/weekly
二十一、修改每日备份脚本
sed -i \\
-e 's#backup_dir="/var/lib/pgsql/backup/daily"#backup_dir="/app/pgbackup/daily"#' \\
-e 's#status_file="/var/lib/pgsql/backup/backup_status.json"#status_file="/app/pgbackup/backup_status.json"#' \\
/var/lib/pgsql/scripts/pg_backup_daily.sh
二十二、修改每周物理备份脚本
sed -i \\
-e 's#backup_dir="/var/lib/pgsql/backup/weekly"#backup_dir="/app/pgbackup/weekly"#' \\
-e 's#status_file="/var/lib/pgsql/backup/backup_status.json"#status_file="/app/pgbackup/backup_status.json"#' \\
/var/lib/pgsql/scripts/pg_backup_weekly.sh
二十三、修正 WAL 清理目录
数据库真正归档:
/app/pgarchive
但当前脚本生成 WAL 清理脚本时,默认路径可能仍为:
/var/lib/pgsql/backup/wal_archive
因此要修改:
sed -i \\
's#wal_archive_dir="/var/lib/pgsql/backup/wal_archive"#wal_archive_dir="/app/pgarchive"#' \\
/var/lib/pgsql/scripts/pg_archive_cleanup.sh
修改周备份判断目录:
sed -i \\
's#find /var/lib/pgsql/backup/weekly#find /app/pgbackup/weekly#' \\
/var/lib/pgsql/scripts/pg_archive_cleanup.sh
日志备份目录:
sed -i \\
's#find "/var/lib/pgsql/backup"#find "/app/pgbackup"#' \\
/var/lib/pgsql/scripts/pg_log_cleanup.sh
当前脚本源码中的 WAL Cleanup 和 Backup Path 确实采用了固定默认路径,因此这一步不是 PostgreSQL 本身的问题,而是当前安装脚本版本的默认设计。PostgreSQL18_Streaming_Replicat…
二十四、统一检查备份路径
grep -nE \\
'backup_dir|status_file|wal_archive_dir|/app/pgbackup|/app/pgarchive' \\
/var/lib/pgsql/scripts/pg_backup_daily.sh \\
/var/lib/pgsql/scripts/pg_backup_weekly.sh \\
/var/lib/pgsql/scripts/pg_archive_cleanup.sh \\
/var/lib/pgsql/scripts/pg_log_cleanup.sh
最终应统一为:
/app/pgbackup/daily
/app/pgbackup/weekly
/app/pgbackup/backup_status.json
/app/pgarchive
二十五、检查定时任务
postgres 用户:
su – postgres
crontab -l
当前安装脚本会生成类似任务:
# 每天02:00逻辑备份
0 2 * * * /var/lib/pgsql/scripts/pg_backup_daily.sh >> /var/log/postgresql/pg_backup_daily.log 2>&1
# 每周日03:00物理备份
0 3 * * 0 /var/lib/pgsql/scripts/pg_backup_weekly.sh >> /var/log/postgresql/pg_backup_weekly.log 2>&1
# 每天04:00清理WAL
0 4 * * * /var/lib/pgsql/scripts/pg_archive_cleanup.sh >> /var/log/postgresql/pg_archive_cleanup.log 2>&1
# 每天05:00清理日志
0 5 * * * /var/lib/pgsql/scripts/pg_log_cleanup.sh >> /var/log/postgresql/pg_log_cleanup.log 2>&1
二十六、手工验证每日逻辑备份
首次部署不能只等 Cron。
立即执行:
/var/lib/pgsql/scripts/pg_backup_daily.sh
检查:
ls -lh /app/pgbackup/daily
状态:
cat /app/pgbackup/backup_status.json
应看到:
"backup_type": "daily_logical"
"status": "success"
二十七、手工验证每周物理备份
/var/lib/pgsql/scripts/pg_backup_weekly.sh
检查:
ls -lh /app/pgbackup/weekly
状态:
cat /app/pgbackup/backup_status.json
应为:
"backup_type": "weekly_physical"
"status": "success"
需要注意:
有备份文件不等于备份体系已经完整。
生产环境还应结合实际情况规划:
异地备份
恢复测试
PITR
备份容量监控
保留周期
二十八、收敛 pg_hba.conf
检查:
cat /app/pgdata/pg_hba.conf
生产不建议长期存在:
host all all 0.0.0.0/0 scram-sha-256
host replication replicator 0.0.0.0/0 scram-sha-256
建议类似:
host all all 192.168.10.0/24 scram-sha-256
host replication replicator 192.168.10.102/32 scram-sha-256
修改后:
su – postgres
psql -c "select pg_reload_conf();"
无需重启 PostgreSQL。
二十九、检查 Standby 核心配置
Standby:
ls -l /app/pgdata/standby.signal
应存在:
standby.signal
查看:
cat /app/pgdata/postgresql.auto.conf
通常可以看到:
primary_conninfo
primary_slot_name
注意:
primary_conninfo 可能包含复制密码,不要将完整内容上传到博客、工单或者截图。
权限建议确认:
stat -c '%a %U:%G %n' /app/pgdata/postgresql.auto.conf
三十、新建环境可选:实际数据复制测试
该步骤仅建议新建 UAT、测试环境执行。
Primary:
CREATE TABLE public.replication_test
(
id integer PRIMARY KEY,
test_time timestamp DEFAULT current_timestamp,
remark varchar(100)
);
INSERT INTO public.replication_test(id,remark)
VALUES (1,'streaming replication test');
Standby:
SELECT * FROM public.replication_test;
能看到数据,说明实际数据复制正常。
验证完成后 Primary:
DROP TABLE public.replication_test;
已上线生产业务的数据库不建议随意建立测试对象。
三十一、PostgreSQL 巡检脚本
统一目录:
mkdir -p /app/pgcheck
上传:
pg_check.sh
配置:
chown -R postgres:postgres /app/pgcheck
chmod 750 /app/pgcheck/pg_check.sh
切用户:
su – postgres
cd /app/pgcheck
export PATH=/app/pgsql/bin:$PATH
确认:
psql –version
主库:
sh pg_check.sh -W -n PGSQL_PRIMARY
备库:
sh pg_check.sh -W -n PGSQL_STANDBY
巡检脚本默认连接:
Host 127.0.0.1
Port 5432
User postgres
Database postgres
所以标准本机部署不需要重复填写 -H -P -u -d。 pg_check
该脚本可以采集主备复制、连接、锁、长 SQL、关键参数以及服务器 CPU、内存、磁盘、IO 等信息,并根据是否处于 Recovery 自动区分 Primary 和 Standby。 pg_check
三十二、部署完成最终验收
部署结束后,我建议固定按照下面这张表验收。
| PostgreSQL Version | Primary / Standby 一致 |
| 服务 | active + enabled |
| 端口 | 5432正常监听 |
| Primary | pg_is_in_recovery() = f |
| Standby | pg_is_in_recovery() = t |
| Primary复制状态 | streaming |
| Standby接收状态 | streaming |
| Replication Lag | 正常范围 |
| Replication Slot | active |
| WAL Archive | failed_count = 0 |
| WAL目录 | /app/pgarchive |
| 日逻辑备份 | success |
| 周物理备份 | success |
| Backup Path | /app/pgbackup |
| pg_hba.conf | 已收敛 |
| Firewall | 最小权限开放 |
| PostgreSQL巡检 | 主备均通过 |
全部满足后,再认为数据库部署完成。
三十三、常见故障速查
| .tar.bz2 无法检查 | 缺 bzip2 | dnf install -y bzip2 |
| icu-uc not found | 缺 ICU Dev | dnf install -y libicu-devel |
| bison not found | 缺编译依赖 | dnf install -y bison flex |
| –repo-mode auto 报错 | 当前脚本不支持 | 删除该参数 |
| WAL有归档但不清理 | Cleanup路径错误 | 改为 /app/pgarchive |
| 备份写根盘 | 默认路径固定 | 改为 /app/pgbackup |
| Primary 无复制记录 | 主备链路未建立 | 查5432、HBA、复制用户 |
| Standby Receiver为空 | 未连上Primary | 查primary_conninfo/网络/密码 |
| Primary WAL暴涨 | Standby故障+Slot保留WAL | 查Slot、Standby和磁盘 |
三十四、以后部署 PostgreSQL 主备的最短流程
如果以后已经熟悉整套流程,实际操作只需要记住:
1. 规划 Primary / Standby / IP / Hostname / 目录
↓
2. 配 Hosts + 时间同步 + 防火墙
↓
3. 检查 /app 数据盘
↓
4. 配好 YUM / DNF Repository
↓
5. 主备安装 PostgreSQL 编译依赖
↓
6. /soft 上传 PgShellInstall + PostgreSQL源码包
↓
7. tar 校验源码包
↓
8. Primary 执行 PgShellInstall streaming部署
↓
9. 验证 PostgreSQL版本和systemd
↓
10. Primary检查 pg_stat_replication
↓
11. Standby检查 pg_stat_wal_receiver
↓
12. 验证 WAL Archive
↓
13. 修正 /app/pgbackup 和 WAL Cleanup目录
↓
14. 手工测试 Daily / Weekly Backup
↓
15. 收敛 pg_hba.conf
↓
16. 主备运行 pg_check.sh
↓
17. 验收完成
这就是后续最值得保留的一张“部署路线图”。
总结
这套部署最终形成的是:
PostgreSQL 18.4
+
AlmaLinux 9
+
PgShellInstall
+
Primary
+
Physical Standby
+
Streaming Replication
+
Replication Slot
+
WAL Archive
+
Daily Logical Backup
+
Weekly Physical Backup
+
PostgreSQL Health Check
自动化部署脚本最大的价值是减少重复安装工作,但生产数据库真正完成交付,还必须经过:
部署
→ 配置检查
→ 主备验证
→ 归档验证
→ 备份验证
→ 安全收敛
→ 巡检验收
因此比较合理的 PostgreSQL 自动化部署理念是:
自动化脚本负责快速部署,DBA负责生产化收口和最终验收。




