news 2026/10/31 7:28:02

PostgreSQL主从流复制+pgpool高可用与pg_rman备份实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PostgreSQL主从流复制+pgpool高可用与pg_rman备份实战

简介:这份资源是一份面向 PostgreSQL 运维与架构人员的《Postgres主从流复制+pgpool高可用方案》技术文档,聚焦数据库主备架构的搭建与高可用保障。内容围绕流复制协议展开,讲解 WAL 日志如何由 walsender 实时推送至备库 walreceiver,并涵盖同步与异步两种复制模式的取舍、pgpool-II 连接池管理、故障自动切换、负载均衡与读写分离、超限连接限制以及 pg_rman 备份恢复等要点,同时给出软件环境规划、环境示意图、用户与权限配置、主库与备库参数调整、pgpool-II 策略设置及启动后故障模拟验证的完整流程,适合需要落地生产级高可用方案的 DBA 或后端开发者参考。资源包仅含 1 个 docx 文档,约 773KB,目录按方案介绍、实践环境、客户环境准备、资源调整等章节组织,便于按步骤对照实施。目前已有 471 人学习下载,可据此梳理主备切换与复制参数配置思路。

1. 主库宕机业务跟着停摆:这套 PostgreSQL 主从流复制加 pgpool 方案解决的是什么

一台数据库服务器在凌晨两点电源故障,应用连接串里写死的那一个 IP 再也连不上,值班的人只能翻文档、改配置、重启服务,业务停摆四十多分钟。这类事故的根子不在数据库本身,而在于单点。这份《Postgres主从流复制+pgpool高可用方案》给的就是从单点到主备的一整套落地路径:用 PostgreSQL 自带的流复制把 WAL 日志实时送到备库,用 pgpool-II 做连接池、读写分离和故障切换,再叠一层 pg_rman 的离线全量与归档备份兜住误删误改。它面向的是 RHEL / CentOS 系发行版上跑中小业务、运维人手只有一两个人的场景——想用开源组件把数据库可用性抬上去,又不想引入商业套件。写入量极大、要求跨机房强一致的场景,这套东西撑不住,得另想办法。

2. 装库之前先把系统层铺平:用户、目录、内核参数与免密登录

很多人拿到方案直接跳到第五章装 PostgreSQL,结果在初始化实例时被共享内存报错、被权限问题卡住、被防火墙拦在第一步。系统层这层土没夯实,后面每一步都会返工。我把这章放在最前面,是因为实际实施里它占的时间比装数据库还长。

2.1 版本怎么搭:三个组件的对应关系

版本搭配是这套方案里最容易埋雷的地方。这份资料里给了两组环境:PostgreSQL 10.3 配 pgpool-II 3.6.14,PostgreSQL 12.2 配 pgpool-II 4.1.1。两组不是随便配的,pgpool-II 每个大版本对 PostgreSQL 的支持范围是有限的,3.6 系列吃不下 PG 12 的部分新特性,4.1 系列才是 PG 12 的对口选择。主备两台机器的 PostgreSQL 版本必须完全一致,小版本也建议一致,否则 WAL 格式、系统表结构出现差异时,备库起来会直接报错。

组件旧环境版本新环境版本部署位置作用
PostgreSQL10.312.2主库、备库数据存储与流复制
pgpool-II3.6.144.1.1主库、备库各一套连接池、读写分离、故障切换
pg_rman与 PG 大版本对应与 PG 大版本对应主库全量/增量备份与恢复

pgpool-II 装在主备两台机器上而不是单独一台,是因为要用 watchdog 做双机互检,虚拟 IP 在两者之间漂移。这一点和"中间件单独一台机器"的常见架构不一样,单机部署 pgpool 反而会引入新的单点。

我一般会把安装目录统一成/opt:PostgreSQL 装/opt/pgsql,pgpool 装/opt/pgpool,备份放/opt/pg_backup。统一路径的好处是后面写脚本时不用为每台机器改路径,pg_rman 的归档目录、备份目录也能直接写死。

2.2 建 postgres 用户、划目录、给权限

所有节点都先做这一步。数据库进程不允许用 root 跑,这是硬约束,不是建议。

# 三个节点统一执行:建用户、建目录、给权限 groupadd -g 1100 postgres useradd -g postgres -u 1100 -m -d /home/postgres -s /bin/bash postgres echo 'Pg@2024#01' | passwd --stdin postgres # 数据库软件目录、数据目录、归档目录、备份目录 mkdir -p /opt/pgsql/{app,data,archive,backup} mkdir -p /opt/pgpool/{app,etc,log} chown -R postgres:postgres /opt/pgsql /opt/pgpool chmod 700 /opt/pgsql/data # 数据目录只允许属主进入 chmod 750 /opt/pgsql/archive # 归档目录允许同组读

/opt/pgsql/data必须是 700,PostgreSQL 启动时会检查这个权限,权限过宽会直接拒绝启动,这是initdb的安全机制。归档目录给 750 是因为 pg_rman 要做校验,有时候还需要运维同组账号进去看文件。密码这一行在离线环境里可以直接用交互式passwd,脚本化时才用--stdin。

这里有个容易被忽略的细节:如果主备两台机器的 postgres 用户 UID 不一致,后面用scp或rsync搬文件时会出属主错乱。脚本里写死-u 1100就是为了避免这个问题,两边 UID 一致,文件传过去不用再 chown。

2.3 防火墙、selinux、hosts 与时钟

这四项属于"不配不一定出事,出事一定查半天"的类型。pgpool 的 watchdog 靠主机名互相通信,hosts 里名字解析不了,watchdog 就起不来,而报错信息往往只告诉你心跳超时。

# 关闭防火墙与 selinux(内网受控环境下的常见做法) systemctl stop firewalld && systemctl disable firewalld setenforce 0 sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config # 主机名与 hosts,两台机器都要有一模一样的条目 hostnamectl set-hostname pg-master cat >> /etc/hosts <<'EOF' 10.0.0.11 pg-master 10.0.0.12 pg-standby 10.0.0.13 pg-vip EOF # 时钟同步,两台机器必须一致 yum install -y chrony systemctl enable --now chronyd chronyc sources -v

时钟同步单独拿出来说:流复制本身对时钟不敏感,但 pgpool 的健康检查和故障判定依赖时间戳,两台机器时间差超过几秒时,watchdog 会出现双方都认为对方死掉的双主风险。chrony 装完务必用chronyc sources确认源是^*状态。

防火墙如果必须开,那至少放行三个端口:PostgreSQL 的 5432(主备复制和 pgpool 后端连接)、pgpool 的 9999(客户端接入)、pgpool 的 9898(watchdog 心跳,配置里可改)。

2.4 sysctl 与 limits:共享内存和文件句柄

PostgreSQL 启动时会把shared_buffers申请成一块共享内存,kernel.shmmax小于这个值时,pg_ctl start会失败并提示 could not create shared memory segment。这个坑在新机器上几乎必踩。

cat >> /etc/sysctl.conf <<'EOF' kernel.shmmax = 68719476736 kernel.shmall = 4294967296 kernel.sem = 50100 64128000 50100 1280 vm.overcommit_memory = 2 vm.swappiness = 10 EOF sysctl -p cat >> /etc/security/limits.conf <<'EOF' postgres soft nofile 65536 postgres hard nofile 65536 postgres soft nproc 65536 postgres hard nproc 65536 EOF

shmmax设成 64GB,够覆盖绝大多数中小业务的shared_buffers配置(一般设物理内存的 25%)。shmall是共享内存总页数,要和 shmmax 匹配,设小了仍然会启动失败。vm.overcommit_memory=2是严格模式,能防止内存超卖导致 OOM killer 杀掉数据库进程,但要求你对机器上跑的东西心里有数;拿不准就用默认的 0。nofile给到 65536,是因为 pgpool 的连接池在高峰期会占大量句柄,默认的 1024 根本不够。

3. 流复制落地:从 postgresql.conf 到 pg_basebackup 的完整链路

流复制的本质是主库的 walsender 进程把 WAL 记录通过 TCP 推给备库的 walreceiver,备库的 startup 进程再把收到的 WAL 重放,本地数据就跟主库对上了。理解了这三个进程的分工,参数怎么调心里就有数:walsender 受max_wal_senders限制,walreceiver 的连接信息写在primary_conninfo里,重放速度决定了备库延迟。

3.1 主库必改的参数与 pg_hba 的一条放行规则

主库的postgresql.conf改动集中在复制、归档、连接三块。我用 12 版本的写法,10 版本把wal_keep_size换回wal_keep_segments即可。

# /opt/pgsql/data/postgresql.conf —— 主库 listen_addresses = '*' # 至少包含主备内网 IP wal_level = replica # 必须有 replica 及以上,否则不开 walsender max_wal_senders = 10 # 并发 walsender 数,主备+pg_basebackup 共用 wal_keep_size = 1GB # 12 起用这个,保留 1GB WAL 给备库追 archive_mode = on archive_command = 'test ! -f /opt/pgsql/archive/%f && cp %p /opt/pgsql/archive/%f' hot_standby = on # 备库可读,读写分离的前提 synchronous_commit = on synchronous_standby_names = 'ANY 1(pg-standby)'

synchronous_standby_names这一行决定了同步还是异步。留空就是异步,主库提交不等备库,延迟低但主库崩溃时可能丢掉最后几百毫秒的事务。写成ANY 1(pg-standby)是同步,主库要等至少一个备库确认收到 WAL 才返回提交成功,牺牲一点写延迟换数据不丢。这里用ANY而不是直接写名字,是为了将来加第二个备库时不用改配置——任意一个备库确认就算数。application_name要和备库的primary_conninfo里写的一致,否则主库认不出是谁,同步复制会一直挂着等。

archive_command里那个test ! -f是防止重复归档同一个文件时报错导致归档卡住,这是很常见的一个小加固。

pg_hba.conf只需要加两条,一条给复制连接,一条给业务连接:

# /opt/pgsql/data/pg_hba.conf —— 追加在文件末尾 host replication repl 10.0.0.0/24 md5 host all all 10.0.0.0/24 md5

第一行的replication是伪数据库名,专门用于流复制连接,不能写成all。第二行放行整个内网段,是因为 pgpool 所在的两台机器都要连过来。如果 pgpool 和后端数据库不在同一网段,这里要单独加 pgpool 的 IP。

3.2 建复制账号与 pg_basebackup 初始化备库

主库启动之后第一件事是建复制账号。这个账号只需要REPLICATION权限,不要给超级用户,减少被滥用的面。

-- 主库执行 CREATE ROLE repl WITH REPLICATION LOGIN PASSWORD 'Repl@2024'; SELECT rolname, rolreplication FROM pg_roles WHERE rolname = 'repl';

然后在备库上执行基础备份,把主库的数据目录整份拉过来。12 版本用-R参数会自动写好 standby 标志和连接信息,比手工写recovery.conf省事得多。

# 备库执行,先把数据目录清空 su - postgres rm -rf /opt/pgsql/data/* pg_basebackup -h 10.0.0.11 -p 5432 -U repl -D /opt/pgsql/data \ -Fp -Xs -P -R -v

-Fp是普通文件格式,-Xs表示流式传输 WAL(避免备份过程中主库 WAL 被清理导致备份不完整),-P显示进度,-R是关键:它在数据目录里生成standby.signal空文件,并把primary_conninfo写进postgresql.auto.conf。12 以前的版本没有-R的完整效果,需要手工创建recovery.conf,内容形如standby_mode = 'on'、primary_conninfo = 'host=10.0.0.11 port=5432 user=repl password=...',主库提升时这个文件会被自动改名为recovery.done——这也是为什么老版本升级到 12 时经常找不到recovery.conf。

备库的postgresql.conf里还要补两行:hot_standby = on(允许只读查询)和primary_conninfo里带上application_name=pg-standby,名字与主库的synchronous_standby_names对齐。

3.3 复制建好之后怎么验:三个视图和一条延迟算法

服务起来不等于复制正常。我见过备库进程活着但一直没收到 WAL 的情况,最后发现是pg_hba少了一行。验收要看三处。

-- 主库:看 walsender 和同步状态 SELECT pid, usename, application_name, client_addr, state, sync_state, sent_lsn, write_lsn, flush_lsn, replay_lsn FROM pg_stat_replication;

state应该是streaming,sync_state在同步复制下是sync,异步下是async。如果这张表是空的,说明备库根本没连上来,去备库日志里找连接失败原因,八成是pg_hba.conf或密码。

-- 主库看当前 LSN,备库看已重放 LSN,两者差值就是延迟 -- 主库 SELECT pg_current_wal_lsn(); -- 备库 SELECT pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();

把两个 LSN 用pg_wal_lsn_diff()一减就得到字节延迟。pg_last_xact_replay_timestamp()更直观,它表示备库最后一次应用事务的时间,和当前时间相减就是"备库落后多少秒"。这个值在空闲库上会很大(因为没有事务可重放),别误判成故障,压一点测试流量再看。

3.4 主备切换:promote 与 pg_rewind

计划内切换和故障切换的操作路径不一样。计划内切换可以先确认备库追平,再提升;故障切换只能直接提。

# 备库提升为主库 su - postgres /opt/pgsql/app/bin/pg_ctl promote -D /opt/pgsql/data # 日志中出现 "database system is ready to accept connections" 即完成

提升之后,原来的主库如果想重新加入集群,两条路:一是用pg_basebackup全量重做,简单但耗时;二是用pg_rewind增量回滚,快但要求主库开启过wal_log_hints = on或者建库时用了--data-checksums。没有这两个前提,pg_rewind会直接拒绝执行,这个限制在故障当天才发现就晚了,建议建库时就把wal_log_hints打开。

4. pgpool-II 接上去:连接池、读写分离与 pcp 管理口的配置取舍

流复制解决了数据同步,但客户端还是得知道连哪台。pgpool-II 的价值在于把两台库藏在 9999 端口后面:应用只认一个地址,pgpool 负责把写发到主库、把读分散到备库、主库挂了自动摘掉。它是中间件不是数据库,配置错了不会报语法错,只会表现为"连接莫名变慢"或"读到了旧数据",所以参数必须一个个对着业务量调。

4.1 pgpool.conf 里真正影响行为的参数

配置文件很长,几百行,但真正决定行为的就那么十几个。下面这段是双节点流复制模式的骨架。

# /opt/pgpool/etc/pgpool.conf listen_addresses = '*' port = 9999 pcp_port = 9898 backend_hostname0 = '10.0.0.11' backend_port0 = 5432 backend_weight0 = 1 backend_flag0 = 'ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER' backend_application_name0 = 'pg-master' backend_hostname1 = '10.0.0.12' backend_port1 = 5432 backend_weight1 = 1 backend_flag1 = 'DISALLOW_TO_FAILOVER' backend_application_name1 = 'pg-standby' enable_pool_hba = on pool_passwd = 'pool_passwd' connection_cache = on max_pool = 4 num_init_children = 100 load_balance_mode = on master_slave_mode = on master_slave_sub_mode = 'stream' health_check_period = 10 health_check_timeout = 20 health_check_user = 'health_check' health_check_password = 'health@2024' health_check_database = 'postgres' sr_check_period = 10 sr_check_user = 'sr_check' sr_check_password = 'sr@2024' sr_check_database = 'postgres'

backend_flag0里的ALWAYS_PRIMARY是 pgpool 4.x 的写法,告诉它 0 号节点永远是首选主库,DISALLOW_TO_FAILOVER表示不把这个节点当作可切换目标(它自己就是主)。backend_application_name要和主库postgresql.conf里的名字对上,pgpool 靠这个在流复制拓扑里识别角色。

max_pool和num_init_children相乘决定了对外能承载的最大连接数:100 个子进程 × 每个 4 条池化连接 = 400。这两个数要和后端 PostgreSQL 的max_connections匹配,配大了会把后端打爆,配小了客户端排队。我一般按后端max_connections的 60% 反推,留出余量给主备复制和人工维护。

health_check_user和sr_check_user必须是后端真实存在的账号,且要能在pg_hba.conf允许的网段内登录。这两个账号只用来探活,给最普通的登录权限就够,别图省事用 postgres 超级用户。

4.2 认证三件套:pool_hba、pool_passwd、pcp.conf

pgpool 自己有一套认证,和后端 PostgreSQL 的认证是两层。客户端连 9999 时先过 pool_hba,再过 pool_passwd,最后才是后端库的 pg_hba。三层有一层没配通,表现都是"密码错误"或"连接被拒"。

# 1. pool_hba.conf:放行客户端网段 cat >> /opt/pgpool/etc/pool_hba.conf <<'EOF' host all all 10.0.0.0/24 md5 EOF # 2. pool_passwd:写入数据库用户的 md5 密码 cd /opt/pgpool/etc /opt/pgpool/app/bin/pg_md5 -p -m -f pool_passwd postgres # 3. pcp.conf:pcp 管理命令的口令 /opt/pgpool/app/bin/pg_md5 -p -m -f pcp.conf pgpool_admin

pg_md5 -m表示用 md5 方式,-p会交互式提示输入密码。写进pool_passwd的账号必须和客户端实际使用的数据库账号一致,postgres只是一个例子。pcp.conf里的账号是给pcp_node_info、pcp_attach_node、pcp_recovery_node这些管理命令用的,和数据库账号不是一回事,别混着配。

pcp 命令是 pgpool 运维的主要入口,几条常用的记牢:

# 查看后端节点状态,0 是主,1 是备,status 为 up/down /opt/pgpool/app/bin/pcp_node_info -h 10.0.0.11 -p 9898 -U pgpool_admin # 手动把掉线的备库挂回去 /opt/pgpool/app/bin/pcp_attach_node -h 10.0.0.11 -p 9898 -U pgpool_admin -n 1 # 在线恢复备库(配合 recovery_1st_stage_command 使用) /opt/pgpool/app/bin/pcp_recovery_node -h 10.0.0.11 -p 9898 -U pgpool_admin -n 1

pcp_recovery_node是这套方案里最值钱的一条命令,它能让备库在故障恢复后自动重建、自动追平、自动挂回集群,不需要人工跑一遍 basebackup。前提是 pgpool.conf 里配好了recovery_1st_stage_command,指向一个在备库上执行恢复的脚本。

4.3 failover 脚本、watchdog 与虚拟 IP

主库挂掉之后,pgpool 要做两件事:把备库提升为主,把虚拟 IP 从故障节点挪走。这两件事靠 failover_command 和 watchdog 配合完成。

# 故障时执行的脚本,%m 旧主节点 ID,%H 新主节点主机名 failover_command = '/opt/pgpool/etc/failover.sh %m %H %P %d' follow_master_command = '/opt/pgpool/etc/follow_master.sh %m %H' # watchdog:双机互检 + 虚拟 IP 漂移 use_watchdog = on hostname0 = 'pg-master' wd_port0 = 9000 pgpool_port0 = 9999 hostname1 = 'pg-standby' wd_port1 = 9000 pgpool_port1 = 9999 delegate_IP = '10.0.0.13' ifconfig_path = '/sbin' if_up_cmd = 'ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0' if_down_cmd = 'ifconfig eth0:0 down' arping_path = '/usr/sbin' arping_cmd = 'arping -U $_IP_$ -w 1 -I eth0'

if_up_cmd和arping_cmd里这两个$_IP_$是 pgpool 的占位符,运行时会被替换成delegate_IP,别手抖改了。arping那一步是给交换机刷新 ARP 表用的,少了它,虚拟 IP 漂移过去了但客户端还在往旧机器发包,现象是"切换成功但业务连不上",非常难查。

执行这些命令需要 root 权限,而 pgpool 一般以普通用户运行,常见做法是把这三条命令写进/etc/sudoers的 NOPASSWD 白名单,并在 pgpool.conf 的if_up_cmd前面加sudo。sudoers 里必须精确到命令行,不要图省事给 ALL。

4.4 验证读写分离是不是真的生效了

配完不验证等于没配。最直接的方式是通过 9999 端口连进去,看查询落在哪台机器上。

-- 通过 pgpool 的 9999 端口连接 SELECT inet_server_addr(), inet_server_port(); -- 这条不会走 pgpool 的负载均衡,因为 inet_server_addr 不是普通查询 SHOW pool_nodes; -- 节点状态、角色、复制延迟 SHOW pool_status; -- 全部运行参数,用来确认配置生效 SHOW pool_pools; -- 连接池使用情况

SHOW pool_nodes输出里每行有status、role、replication_delay三列。role显示 primary / standby,replication_delay是 pgpool 自己算出来的延迟。如果status一直是down而库里明明活着,八成是health_check_user登不进去,去 pgpool 日志里搜health check failed能看到具体原因。

读写分离的验证要靠执行计划和日志。开log_statement = 'all'太吵,我一般开log_min_duration_statement = 200,然后把log_perror = on打开,在 pgpool 日志里看DB node id: 1这类记录,确认 select 确实被发到了 1 号节点。

5. 避坑与排查:failover 演练里最常见的五个翻车现场

配置写完只是开始,真正的成本在演练和排错。下面这五条都是我实际踩过或者帮人收拾过的,按出现频率排。每条的现象都很有迷惑性,光看报错很容易走偏。

5.1 备库起不来,日志只说找不到 recovery.conf

现象:备库执行pg_ctl start,日志里一行FATAL: could not open file "recovery.conf"或者干脆静默退出,进程列表里连 startup 进程都没有。

原因是版本差异。PostgreSQL 12 开始彻底移除了recovery.conf,改用数据目录下的standby.signal空文件加postgresql.conf(或postgresql.auto.conf)里的primary_conninfo。方案文档里同时给了"12.X 以前版本"和"12.X 以后版本"两套写法,照抄错版本就会这样。

解决:确认PG_VERSION文件里的大版本号,12 及以上只建standby.signal,把连接串写进postgresql.auto.conf。用pg_basebackup -R的话这一步是自动完成的,所以能用-R就别手工写。

5.2 连接报 no pg_hba.conf entry for host

现象:客户端连 9999 端口,或者 pgpool 连后端 5432,报no pg_hba.conf entry for host "10.0.0.11", user "repl", database "replication"。

原因有三层,要按层排查。第一层是后端的pg_hba.conf没放行 pgpool 所在机器的 IP;第二层是放了行但数据库名写成了all而不是replication,流复制连接匹配不上;第三层是 pgpool 自己的pool_hba.conf没放行客户端。三层都长得一样,只能一层层试。

解决:先确认报错发生在哪一跳——报错信息里的 host 如果是客户端 IP,说明卡在 pool_hba;如果是 pgpool 的 IP,说明卡在后端 pg_hba。改完pg_hba.conf一定要pg_ctl reload,这个文件支持 reload 不需要重启。

5.3 pool_nodes 里节点全 down,但数据库明明活着

现象:SHOW pool_nodes两行都是 down,客户端连不上,可手动psql -h 10.0.0.11 -U postgres完全正常。

原因是health_check_user这个账号不存在,或者密码和health_check_password对不上。pgpool 探活失败就判定节点死掉,直接摘掉,哪怕后端服务好好的。另一个常见原因是探活账号在pg_hba.conf里没被放行,密码再对也没用。

解决:手工用health_check_user登录一次后端库,能进说明账号没问题;进不去就看pg_hba。确认后从 pgpool 日志里搜health check failed,它会明确告诉你失败在哪一步。改完配置要重启 pgpool,健康检查参数不支持 reload。

5.4 虚拟 IP 漂了,业务还是连不上

现象:主库宕机后,ip addr在新节点上能看到 VIP,但客户端连接依然超时或者连到旧机器。

原因通常是三个。一是arping_cmd没执行成功,交换机 ARP 表还是旧 MAC,包被送到已经下线的机器;二是if_up_cmd里的网卡名和实际不符,比如配的是eth0而机器上是ens33;三是 sudo 权限没给对,pgpool 日志里能看到Permission denied但被淹没在大量心跳日志里。

解决:先在新节点上手工执行一遍if_up_cmd和arping_cmd的命令体,确认能配上地址;再检查 sudoers;最后用一个不相关的客户端持续 ping VIP,切换时观察丢包多久恢复。这一步必须在演练环境做,生产上第一次发现就晚了。

5.5 同步复制下备库一停,主库写入直接卡死

现象:备库因为维护停机,主库的 insert 全部挂住,应用超时,主库 CPU 不高但连接堆积。

原因是synchronous_commit = on加synchronous_standby_names配了固定名字,主库会一直等那个备库确认。备库不在线,事务就永远提交不了。这在异步复制下不会发生,所以很多人第一次遇到会怀疑是锁或者磁盘问题。

解决:短期把synchronous_standby_names改成ANY 1(pg-standby, pg-standby2),任意一个在线即可;长期要么准备第二个备库,要么评估能不能接受异步复制的少量数据丢失风险。还有一个办法是把synchronous_commit降成local,但这就等于放弃了同步语义,得和业务方确认。

6. pg_rman 补上后悔药:归档、全量与恢复演练

流复制扛的是机器故障,扛不住DELETE忘写WHERE。方案里第十一章的 pg_rman 就是为这个准备的——它把全量备份、增量备份和 WAL 归档串起来,能恢复到任意时间点。配置的前提是主库已经开了archive_mode = on并且archive_command真的在工作,这一点可以用下面的语句验证,返回值必须是on且归档目录里有文件持续产生。

SELECT name, setting FROM pg_settings WHERE name IN ('archive_mode','archive_command'); SELECT last_archived_wal, last_archived_time FROM pg_stat_archiver;

pg_rman 的日常使用就四条命令:

# 初始化备份目录(只需一次) pg_rman init -B /opt/pgsql/backup --with-serverlog # 全量备份 + 校验 pg_rman backup -B /opt/pgsql/backup -D /opt/pgsql/data --backup-mode=full -C pg_rman validate -B /opt/pgsql/backup # 恢复到指定时间点(需先停库) pg_rman restore -B /opt/pgsql/backup -D /opt/pgsql/data \ --recovery-target-time='2024-05-20 03:00:00'

--with-serverlog把数据库日志一起备进去,排查恢复问题时很有用。-C是备份后立即校验,不校验的备份等于没有备份。恢复时--recovery-target-time精确到秒,恢复到误操作之前的那一刻,然后把数据导出来再导回生产库——不要直接拿恢复库顶上生产,中间还差一次数据核对。

备份策略我用的是每周日全量、周一到周六增量、归档持续保留两周。脚本层面就是两个 shell,一个全量一个增量,挂 cron 跑,跑完把pg_rman show的输出重定向到日志文件,第二天早上扫一眼。表结构上值得记一下 pg_rman 的三个目录:backup/存备份集、arclog/存归档、srvlog/存服务器日志,恢复时三个目录缺一不可。

真正让我养成习惯的是一次演练:备份脚本天天跑成功,但从没做过恢复验证,真要用的时候才发现归档目录权限不对,恢复卡在第二个 WAL 文件上。从那以后我每次改完备份配置,都强制走一遍"备份 → validate → 恢复到临时目录 → 起库 → 比对行数"的完整链路,不管多麻烦。这套方案的脚本和配置在资源包里都有现成的,按上面的顺序走一遍,比自己从零拼要快得多。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/31 7:28:00

OData中Functions与Actions的区别及SAP实现

1. 理解OData中的Functions与Actions基础概念在SAP技术生态中&#xff0c;Functions和Actions是OData协议中定义业务操作的两大核心机制。虽然它们都用于执行特定操作&#xff0c;但设计理念和使用场景有着本质区别。Functions&#xff08;函数&#xff09;在OData中属于查询操…

作者头像 李华
网站建设 2026/10/31 7:27:03

模型预测控制(MPC)技术演进与工程实践

1. MPC技术演进全景图模型预测控制&#xff08;Model Predictive Control&#xff0c;MPC&#xff09;作为现代控制理论的重要分支&#xff0c;在过去十年间经历了从工业过程控制到智能系统应用的跨越式发展。这项起源于化工领域的高级控制方法&#xff0c;如今已渗透到机器人、…

作者头像 李华
网站建设 2026/10/31 7:27:00

SQL Server 动态拼接 JSON 的原理与避坑指南

简介&#xff1a;本资源是一份面向SQL Server数据库开发人员与后端工程师的实用技术文档&#xff0c;聚焦于利用T-SQL动态生成标准JSON数据的核心方法&#xff0c;解决传统关系型数据向Web前端或API接口高效输出结构化JSON的常见痛点。文档详细拆解了基于SYS.SYSCOLUMNS元数据自…

作者头像 李华
网站建设 2026/10/31 7:26:31

从RNN到BiLSTM:序列模型演进与自然语言处理实践

1. 序列模型演进全景图在自然语言处理领域&#xff0c;我们常常需要处理具有时序特性的数据。传统的前馈神经网络&#xff08;FNN&#xff09;在处理这类数据时存在明显局限——它们假设所有输入样本相互独立。这种假设与语言理解的本质相悖&#xff0c;因为人类理解语句时&…

作者头像 李华
网站建设 2026/10/31 7:25:59

环境变量与命令行参数:开发配置的核心解析

1. 环境变量与命令行参数基础解析环境变量和命令行参数是软件开发中两个看似简单却至关重要的概念。作为从业15年的全栈工程师&#xff0c;我见过太多项目因为这两者的配置不当而导致各种"灵异问题"。今天我们就来彻底搞懂它们的本质区别和实际应用。环境变量是操作系…

作者头像 李华
网站建设 2026/10/31 7:25:56

云原生时代Tomcat容器化实践与优化指南

1. 云原生时代下的Tomcat容器化实践十年前我第一次在物理服务器上部署Tomcat时&#xff0c;手动配置JDK环境、修改server.xml的场景还历历在目。如今在云原生浪潮下&#xff0c;Tomcat的部署方式已经发生了翻天覆地的变化。作为Apache软件基金会的老牌Servlet容器&#xff0c;T…

作者头像 李华