1. 项目概述:为什么在Windows上做PostgreSQL主从流复制,不是“折腾”,而是刚需
PostgreSQL主从集群流复制从无到有搭建(Windows架构)——这个标题里藏着三个关键信号:PostgreSQL、流复制(Streaming Replication)、Windows环境。很多人看到“Windows + 数据库高可用”第一反应是皱眉,觉得“Linux才是正统”,“Windows跑数据库不专业”。但现实是:某高校实验室的科研数据平台、某制造企业的本地MES系统、某医疗设备厂商的边缘数据采集终端,大量真实业务场景就部署在Windows Server或甚至Windows 10/11专业版上。它们不需要动辄百节点的云原生集群,但必须解决一个朴素问题:主库宕机了,业务不能停,数据不能丢,切换不能靠人工重启服务再改连接字符串。流复制就是那个最轻量、最稳定、最贴近PostgreSQL内核设计的方案。它不依赖第三方中间件,不引入额外网络跳转,主库WAL日志生成后,从库几乎实时接收并重放,RPO(恢复点目标)可控制在秒级,RTO(恢复时间目标)在手动触发故障转移时通常低于30秒。我去年帮一家做工业视觉检测的客户落地这套方案时,他们原有单点PostgreSQL实例一旦蓝屏或意外断电,产线质检数据就丢失一整批,重跑标注要4小时。上线流复制后,主库异常时,运维人员按一个PowerShell脚本,22秒完成从库提升(promote),应用连接池自动重连,产线零感知。这背后没有魔法,只有对Windows服务机制、PostgreSQL WAL归档逻辑、pg_hba.conf权限粒度、以及Windows防火墙与PostgreSQL端口策略之间那几毫米缝隙的反复抠细节。本文不讲“理论可行”,只讲“实操能跑通”的每一步:从Windows系统准备开始,到主库初始化、从库基础同步、流复制通道建立、故障模拟与切换验证,全部基于Windows原生环境,不装WSL,不借Docker Desktop,不碰Linux虚拟机。适合所有正在用Windows跑PostgreSQL、又不想把生产环境迁到Linux、但急需高可用兜底能力的开发者、DBA和系统集成工程师。你不需要是Windows注册表专家,也不必精通PostgreSQL源码,只要能打开命令提示符、编辑文本文件、理解“服务”和“端口”这两个概念,就能照着一步步搭出来。
2. 整体架构设计与方案选型逻辑:为什么是流复制,而不是逻辑复制或第三方工具
2.1 流复制 vs 逻辑复制:本质差异决定适用边界
在PostgreSQL生态里,“复制”不是单一技术,而是一组分层能力。流复制(Physical Replication)和逻辑复制(Logical Replication)常被混淆,但它们解决的问题根本不同。流复制是物理块级别的复制,主库将WAL(Write-Ahead Logging)日志文件中的每一个字节变更,通过TCP流实时发送给从库;从库接收到后,不做任何SQL解析,直接按顺序重放这些WAL记录,使从库的数据文件(data directory)与主库完全一致。它的核心优势是零语义损耗、最高一致性、最低延迟、最简配置。而逻辑复制是逻辑行级别的复制,主库先将WAL日志解析成“INSERT/UPDATE/DELETE”等逻辑操作,再通过逻辑解码插件(如pgoutput)发送给订阅者;订阅者收到后,再把这些逻辑操作转换成SQL,在目标库上执行。它支持跨版本复制、表级过滤、部分列同步,但代价是:延迟更高(多一层解析+执行)、一致性更难保证(事务边界可能被拆分)、配置更复杂(需创建publication/subscription)。对于“主从集群高可用”这个明确目标,逻辑复制是杀鸡用牛刀——你不需要跨版本兼容,不需要只同步某几张表,你只需要一个1:1镜像,随时能顶上去。我试过在Windows上配逻辑复制,光是wal_level参数调成logical、安装pglogical插件、处理二进制依赖链,就卡了三天。而流复制,核心配置就三行:wal_level = replica、max_wal_senders = 10、archive_mode = off(流复制下归档非必需)。这是方案选型的第一道铁律:目标决定技术栈,不是技术炫技。
2.2 为什么拒绝Pgpool-II、Patroni等第三方高可用套件
市面上有很多PostgreSQL高可用方案,比如Pgpool-II(连接池+负载均衡+自动故障转移)、Patroni(基于分布式配置中心的故障检测与主库选举)。它们功能强大,但引入了新维度的复杂性。以Patroni为例,它需要额外部署etcd或Consul作为协调服务,每个PostgreSQL节点上还要跑一个Patroni进程监听状态,故障判断依赖心跳超时和分布式锁。在Windows环境下,etcd官方不提供原生Windows服务安装包,得自己编译或找社区非官方版本;Patroni的Python依赖在Windows上常因路径空格、权限模型差异报错;更麻烦的是,当主库因磁盘满导致WAL写失败时,Patroni可能误判为“网络分区”,触发脑裂(split-brain)——两个节点同时认为自己是主库,写入冲突。我参与过一个项目,客户硬上了Patroni,结果一次Windows更新后服务启动顺序错乱,etcd没起来,Patroni起不来,PostgreSQL也起不来,整个集群瘫痪6小时。而纯流复制方案,没有外部依赖,所有逻辑都在PostgreSQL自身进程内:主库是sender,从库是receiver,状态通过pg_stat_replication视图暴露,故障转移只需一条pg_ctl promote命令。它像一把瑞士军刀,功能不多,但每一项都打磨到极致可靠。在Windows这种以“服务稳定性”而非“进程灵活性”见长的系统上,少一个依赖,就少十个潜在故障点。所以我们的架构极简:一台Windows Server 2019(主库),一台Windows 10 Pro(从库),两台机器在同一局域网,通过TCP 5432端口直连,无代理、无中间件、无协调服务。所有高可用逻辑,由DBA写的PowerShell脚本和Windows任务计划程序兜底——简单,才可控。
2.3 Windows平台特殊性带来的设计约束与补偿
Windows和Linux在进程管理、文件权限、服务注册、网络栈上的差异,是流复制落地的最大拦路虎。Linux下,pg_ctl start默认以后台守护进程运行,日志自动轮转,信号(SIGUSR1)可优雅通知进程重载配置;Windows下,pg_ctl启动的是前台控制台进程,关掉CMD窗口服务就停,日志默认打到控制台,重载配置得发Windows消息。我们不得不做三处关键补偿:
第一,服务化封装:不用pg_ctl直接启停,而是用pg_ctl register将PostgreSQL注册为Windows服务,这样它能随系统启动、在用户未登录时运行、受Windows服务管理器监控。注册命令是pg_ctl register -N "postgresql-master" -D "C:\pgdata\master" -w,其中-N指定服务名,-D指定数据目录,-w表示等待服务启动完成。
第二,日志重定向:Windows服务无法捕获控制台输出,必须显式配置日志路径。在postgresql.conf中设置log_destination = 'csvlog'和logging_collector = on,再指定log_directory = 'pg_log'和log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log',确保所有日志落盘可查。
第三,防火墙白名单:Windows Defender防火墙默认阻止入站连接。必须手动添加入站规则,允许TCP 5432端口(主库)和5433端口(从库,避免端口冲突)的专用连接。命令是netsh advfirewall firewall add rule name="PostgreSQL Master" dir=in action=allow protocol=TCP localport=5432。这三步不是可选项,是Windows流复制的生存底线。漏掉任何一个,你的从库永远连不上主库,报错永远停留在“connection refused”。
3. 核心细节解析与实操要点:Windows专属坑点与绕过技巧
3.1 PostgreSQL安装与数据目录初始化:避开Windows路径陷阱
PostgreSQL官方Windows安装包(EnterpriseDB版)虽方便,但默认安装路径含空格(如C:\Program Files\PostgreSQL\15),这在后续pg_basebackup、pg_ctl命令中极易引发参数解析错误。例如,pg_basebackup -D "C:\Program Files\PostgreSQL\15\data"会被shell误判为三个参数。解决方案只有一个:强制自定义安装路径,且路径中不含空格、中文、特殊字符。我推荐C:\pg\15——短、直、安全。安装时勾选“Initialize database cluster”,但不要勾选“Install pgAdmin”和“Stack Builder”,它们会额外安装Python、Java等运行时,增加系统负担和安全面。初始化完成后,立即修改数据目录权限:右键C:\pg\15\data→ “属性” → “安全” → “编辑” → 添加“SYSTEM”和“Administrators”组,赋予“完全控制”权限。这是Windows特有要求——PostgreSQL服务进程(以Local System身份运行)必须对data目录有读写权,否则启动时报“could not open file 'global/pg_filenode.map': Permission denied”。另外,务必确认pg_hba.conf初始内容已包含host all all 127.0.0.1/32 trust,这是本地管理的基础信任链。很多新手卡在这一步,以为安装完就能连,结果psql -U postgres死活连不上,其实是hba规则没放行本地回环地址。
3.2 主库配置深度调优:wal_level、max_wal_senders与同步策略取舍
主库的postgresql.conf是流复制的心脏,三处参数决定成败。第一,wal_level必须设为replica(PostgreSQL 10+)或hot_standby(旧版),这是开启流复制的前提。设为logical会额外开销,没必要;设为minimal则WAL日志不包含足够信息供从库重放。第二,max_wal_senders定义主库最多允许多少个并发WAL发送进程。值太小(如默认的10),当从库重建或网络抖动重连时,新连接被拒绝;值太大(如100),会占用过多内存。经验公式:max_wal_senders = 从库数量 × 2 + 2。我们只有一台从库,设为4足够。第三,synchronous_commit和synchronous_standby_names决定是否启用同步复制。同步复制要求主库写入WAL后,必须等至少一个从库确认接收并刷盘才返回成功,RPO=0但性能下降30%以上。对于大多数Windows场景,异步复制(默认)更务实:主库写完即返回,从库尽力追,RPO<1秒,性能无损。若真需要强一致,synchronous_standby_names = 'FIRST 1 (standby1)',并在从库postgresql.conf中设application_name = 'standby1'。注意:application_name必须与synchronous_standby_names中名称严格匹配,大小写敏感,Windows下尤其容易因复制粘贴带隐藏空格而失败。我踩过的坑是,从库配置里写了application_name = ' standby1 '(前后有空格),主库日志里一直报“no synchronous standby with name 'standby1' found”,查了两小时才发现是空格惹的祸。
3.3 从库初始化:pg_basebackup的Windows实战参数详解
从库不能自己初始化,必须从主库克隆一份全量数据快照。pg_basebackup是唯一标准工具,但它在Windows下的参数组合极易出错。核心命令是:
pg_basebackup -h 192.168.1.100 -p 5432 -U replicator -D "C:\pg\15\slave" -P -X stream -v -Fp -R逐参数拆解:
-h 192.168.1.100:主库IP,必须用IP,不能用主机名。Windows DNS解析在服务环境下不稳定,且pg_hba.conf中host规则按IP匹配,用主机名可能导致认证失败。-p 5432:主库端口,确认主库postgresql.conf中port = 5432且防火墙放行。-U replicator:连接用户,不能是postgres超级用户!必须新建专用复制用户,最小权限原则。创建语句:CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'StrongPass123!';,并在pg_hba.conf中加一行:host replication replicator 192.168.1.101/32 md5(192.168.1.101是从库IP)。-D "C:\pg\15\slave":从库数据目录,路径必须存在且为空,权限同主库data目录。-P:显示进度条,Windows CMD下友好可见。-X stream:启用流复制模式,备份过程中主库持续发送WAL,保证从库启动时WAL连续。不加此参数,备份完再传WAL,间隙期数据丢失。-v:详细日志,排错必备。-Fp:输出格式为plain(普通文件),不是tar。Windows解压tar易出编码问题。-R:最关键参数!它让pg_basebackup自动生成standby.signal文件,并在postgresql.auto.conf中写入primary_conninfo连接串。没有-R,从库启动就是只读主库,不是流复制从库。
执行后,你会看到类似progress: 123456789/123456789 kB (100%), 1/1 tablespace的输出。完成后,检查从库C:\pg\15\slave目录下是否有standby.signal文件(空文件,仅存在即生效)和postgresql.auto.conf中是否包含primary_conninfo = 'user=replicator password=StrongPass123! host=192.168.1.100 port=5432 sslmode=disable'。这是从库能否启动为只读备库的生死线。
3.4 连接认证与权限控制:pg_hba.conf的Windows精调指南
pg_hba.conf是PostgreSQL的“门禁系统”,Windows环境下它比Linux更敏感。常见错误是:主库能连,从库连不上;或者从库能连,但流复制不启动。根源几乎都在hba规则顺序和匹配精度。规则按文件从上到下顺序匹配,第一条匹配即生效,后续忽略。因此,必须把最具体的规则放前面。一个健壮的Windows流复制hba配置应如下:
# TYPE DATABASE USER ADDRESS METHOD host replication replicator 192.168.1.101/32 md5 host all replicator 192.168.1.101/32 reject host all all 127.0.0.1/32 trust host all all ::1/128 trust host all all 192.168.1.0/24 md5解释:
- 第一行:专为流复制开的绿灯,只允许从库IP(192.168.1.101)用replicator用户连replication数据库,用md5密码认证。这是流复制的命脉。
- 第二行:堵死replicator用户访问其他数据库的路,
reject比md5更安全,防止误用。 - 第三、四行:本地管理通道,信任回环地址,免密登录。
- 第五行:业务网段通用访问,密码认证。
绝对禁止在hba中写host all all 0.0.0.0/0 md5(全网开放),这等于把数据库裸奔在公网。Windows防火墙虽能拦截,但hba是最后一道逻辑防线。修改hba后,必须执行pg_ctl reload(或Windows服务中右键“刷新”)重载配置,不是重启服务。重启会中断现有连接,而reload只更新配置,平滑生效。我见过客户因改hba后直接重启服务,导致正在执行的大事务被强制终止,业务报错。
4. 实操过程与核心环节实现:从零开始的完整搭建流水线
4.1 环境准备清单与系统级预检
在敲第一个命令前,必须完成五项Windows系统级检查,缺一不可:
- 时间同步:主从库系统时间差必须<5秒,否则WAL时间戳校验失败。在管理员CMD中运行:
w32tm /resync /force,强制从域控制器或NTP服务器同步。检查命令:w32tm /query /status,看“Last Successful Sync Time”是否为最近时间。 - 磁盘空间:从库数据目录所在磁盘剩余空间 ≥ 主库data目录大小 × 1.5。因为pg_basebackup期间主库WAL会持续增长,且从库启动后需保留WAL归档(即使不启用archive_mode,流复制缓冲区也占空间)。用
df -h(WSL)不适用,Windows下看“此电脑”图标属性,或PowerShell命令:Get-PSDrive C | Select-Object Used, Free。 - Windows服务状态:确认主库PostgreSQL服务已启动且为“正在运行”。在服务管理器(services.msc)中查找服务名(如“postgresql-x64-15”),右键“属性”→“常规”→“启动类型”设为“自动”,“服务状态”为“正在运行”。
- Telnet连通性验证:在从库机器上,用管理员CMD执行:
telnet 192.168.1.100 5432。如果黑屏闪退,说明网络不通或主库防火墙未放行;如果出现空白光标,说明端口可达,可进入下一步。这是比psql更底层的连通性测试。 - PowerShell执行策略:后续自动化脚本需用PowerShell,而Windows默认策略为
Restricted,禁止脚本运行。临时提权:以管理员身份运行PowerShell,执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser。这仅对当前用户生效,安全且必要。
完成这五步,你才真正站在了“可以开始搭建”的起点。跳过任一检查,后续90%的失败都源于此。
4.2 主库配置实施:逐行修改postgresql.conf与pg_hba.conf
登录主库Windows,用记事本(不要用WordPad或富文本编辑器)打开C:\pg\15\data\postgresql.conf。找到以下参数,取消注释(删掉行首#)并修改值:
listen_addresses = '192.168.1.100' # 必须指定具体IP,不能用'*'或'localhost',Windows下'localhost'可能解析为::1(IPv6) port = 5432 max_connections = 100 shared_buffers = 128MB wal_level = replica max_wal_senders = 4 max_replication_slots = 4 # 预留槽位,便于未来加更多从库 hot_standby = on # 允许从库在恢复中提供只读查询 archive_mode = off # 流复制下归档非必需,设off减少I/O log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' log_statement = 'ddl' # 记录建表删表等DDL,便于审计保存后,打开同目录pg_hba.conf,在文件末尾添加前述五条规则(复制粘贴即可)。关键动作:用管理员CMD执行pg_ctl reload -D "C:\pg\15\data"。观察命令行返回“server signaled”即成功。此时,主库已具备流复制发射能力,但尚未有接收者。
4.3 从库初始化与启动:pg_basebackup执行与验证
在从库Windows上,确保C:\pg\15\slave目录已创建且为空。以管理员身份打开CMD,执行前述pg_basebackup命令。全程约需10-30分钟,取决于主库数据量。成功后,检查:
C:\pg\15\slave\standby.signal文件是否存在(0字节);C:\pg\15\slave\postgresql.auto.conf中primary_conninfo是否正确(重点核对IP、端口、用户名、密码);C:\pg\15\slave\pg_wal\archive_status\目录下是否有.ready文件(流复制启动后自动生成)。
然后,用pg_ctl register将从库注册为Windows服务:
pg_ctl register -N "postgresql-slave" -D "C:\pg\15\slave" -w启动服务:net start postgresql-slave。启动后,立刻检查日志:C:\pg\15\slave\pg_log\postgresql-*.log。正常日志应包含:
2023-10-05 14:22:31.123 UTC [1234] LOG: entering standby mode 2023-10-05 14:22:31.456 UTC [1234] LOG: redo starts at 0/3000000 2023-10-05 14:22:31.789 UTC [1234] LOG: consistent recovery state reached at 0/3000028 2023-10-05 14:22:31.789 UTC [1234] LOG: database system is ready to accept read only connections最后,登录从库验证:psql -h 127.0.0.1 -U postgres -c "SELECT pg_is_in_recovery();",返回t(true)即成功。再查SELECT * FROM pg_stat_replication;,主库上应看到一行记录,state = 'streaming',sync_state = 'async'(异步)或'sync'(同步)。
4.4 故障转移模拟与切换验证:手动promote全流程
高可用的价值不在平时,而在故障时。模拟主库宕机:在主库服务管理器中,右键“postgresql-master”服务 → “停止”。等待10秒,确认服务状态为“已停止”。此时,从库仍在运行,但状态变为state = 'startup'(因主库失联,尝试重连)。现在,执行故障转移:在从库管理员CMD中运行:
pg_ctl promote -D "C:\pg\15\slave"成功后,从库日志出现:
2023-10-05 14:30:00.000 UTC [1234] LOG: received promote request 2023-10-05 14:30:00.123 UTC [1234] LOG: redo done at 0/4000000 2023-10-05 14:30:00.123 UTC [1234] LOG: selected new timeline ID: 2 2023-10-05 14:30:00.456 UTC [1234] LOG: database system is ready to accept connections此时,从库已升为主库。验证:psql -h 127.0.0.1 -U postgres -c "SELECT pg_is_in_recovery();"返回f(false),且可执行CREATE TABLE test_failover (id SERIAL);。业务应用只需将连接字符串中的host从192.168.1.100改为192.168.1.101,即可无缝续用。注意:原主库恢复后,不能直接启动,否则成为独立分支,造成数据分裂。必须将其作为新从库重建:删掉C:\pg\15\master目录,重新pg_basebackup从新主库同步。这就是流复制的“单主”本质——切换是破坏性的,但可控。
5. 常见问题与排查技巧实录:Windows流复制故障速查手册
5.1 连接类问题:从库报“connection refused”或“password authentication failed”
这是最高频问题,根因90%在pg_hba.conf或Windows防火墙。排查流程:
- 查主库服务状态:
sc query postgresql-master,确认STATE为4 RUNNING。 - 查主库监听端口:
netstat -ano | findstr :5432,确认有LISTENING状态,且PID对应PostgreSQL进程(用tasklist | findstr <PID>确认)。 - 查防火墙规则:
netsh advfirewall firewall show rule name="PostgreSQL Master",确认Enabled为Yes,Direction为In,Protocol为TCP,LocalPort为5432。 - 查hba规则匹配:在主库psql中执行
SELECT * FROM pg_hba_file_rules();,确认你的从库IP(192.168.1.101)匹配到了host replication replicator 192.168.1.101/32 md5这一行,且line_number是最小的有效行号。 - 查密码是否正确:在从库CMD中手动测试连接:
psql -h 192.168.1.100 -U replicator -d replication,输入密码。若失败,密码错误;若成功,说明hba或防火墙有问题。
提示:Windows下密码含特殊字符(如
!、$)时,CMD会尝试变量替换。解决方案:用双引号包裹整个连接串,或改用PowerShell执行:& "C:\pg\15\bin\psql.exe" -h 192.168.1.100 -U replicator -d replication
5.2 复制停滞类问题:从库WAL落后、pg_stat_replication显示state=‘startup’
从库启动后,pg_stat_replication中state长期为startup,或sent_lsn与write_lsn差距巨大(>1GB),说明WAL传输卡住。原因及解法:
- 主库WAL归档阻塞:虽然
archive_mode=off,但若主库archive_command未清空,PostgreSQL仍会尝试执行,失败后WAL文件不回收。检查主库postgresql.conf中archive_command是否为''(空字符串)或注释掉。 - 从库磁盘满:
C:\pg\15\slave\pg_wal\目录爆满。Windows下WAL文件不会自动清理,需确保max_wal_size合理(默认1GB),并监控磁盘。清理命令:pg_archivecleanup "C:\pg\15\slave\pg_wal" 000000010000000000000001(参数为最后一个已应用的WAL文件名)。 - 网络抖动丢包:Wireshark抓包发现TCP重传率>5%。解决方案:在主库
postgresql.conf中加大tcp_keepalives_idle = 60、tcp_keepalives_interval = 10、tcp_keepalives_count = 6,增强保活。
注意:
pg_stat_replication中replay_lsn代表从库已重放的WAL位置,write_lsn是已写入磁盘的位置,flush_lsn是已刷盘的位置。三者应基本一致,若replay_lsn远小于write_lsn,说明重放慢于写入,可能是从库CPU或I/O瓶颈。
5.3 权限与路径类问题:pg_basebackup报“permission denied”或“could not open file”
Windows权限模型是罪魁祸首。典型报错:
pg_basebackup: error: could not open file "global/pg_filenode.map": Permission denied:主库data目录权限不足。解决方案:右键目录→“属性”→“安全”→“编辑”→添加SYSTEM和Administrators,勾选“完全控制”。pg_basebackup: error: could not create directory "C:\pg\15\slave": Permission denied:从库目标目录父路径无写入权。解决方案:确保C:\pg\15目录对当前用户(运行pg_basebackup的用户)有“修改”权限。pg_basebackup: error: could not change permissions of directory "C:\pg\15\slave": Operation not permitted:从库目录在OneDrive或SharePoint同步文件夹内。Windows对云同步目录的权限控制极严。解决方案:绝对禁止将PostgreSQL数据目录放在任何云同步路径下,必须用本地物理磁盘(如C:\或D:\)。
5.4 切换后业务异常:新主库无法写入或应用连接失败
故障转移后,应用连上新主库却报read-only transaction,说明从库未真正promote成功。检查:
- 新主库日志中是否有
received promote request和database system is ready to accept connections; - 执行
SELECT pg_is_in_recovery();,必须返回f; - 检查新主库
postgresql.conf中listen_addresses是否包含其自身IP(192.168.1.101),否则应用从其他网段连不上。
若应用连接字符串未及时更新,可临时在新主库上创建pg_hba.conf规则,允许旧主库IP(192.168.1.100)的连接,但这是临时补救,长期必须更新应用配置。
实操心得:我写了一个一键切换PowerShell脚本,包含三步:1. 检查原主库是否真宕机(ping + 端口探测);2. 执行
pg_ctl promote;3. 自动修改应用配置文件中的数据库IP。脚本开头加#Requires -RunAsAdministrator,确保权限。这比人肉操作快10倍,且零失误。
6. 后续演进与维护建议:让Windows流复制真正“省心”
搭建完成只是起点,日常维护才是关键。我给客户的三条硬性建议:
第一,监控必须前置。不要等业务报警才查。在从库上建一个Windows计划任务,每5分钟执行:psql -h 127.0.0.1 -U postgres -c "SELECT now() - pg_last_xact_replay_timestamp() AS lag;" > C:\pg\lag.log,将复制延迟写入日志。用PowerShell脚本读取该文件,若lag > '30 seconds',自动邮件告警。这比Zabbix等重型监控更适合Windows轻量场景。
第二,定期演练切换。每季度至少一次真实故障转移演练:停主库、促从库、切应用、验数据、重建旧主库。演练不是走形式,要记录从触发到业务恢复的精确秒数,优化脚本。我经手的项目,首次演练RTO 127秒,第三次压到22秒。
第三,版本升级策略。PostgreSQL大版本升级(如15→16)不能原地升级流复制集群。必须:1. 在新版本上初始化空主库;2. 用pg_dump导出旧主库全量数据;3. 导入新主库;4. 用新主库pg_basebackup重建所有从库。小版本(15.1→15.4)可直接覆盖安装,但必须先停服务、备份data目录、再覆盖bin目录。
最后分享一个血泪教训:某客户在从库上误删了standby.signal文件,从库自动降级为只读主库,但未报错。业务写入失败才发现。从此,我在所有从库上加了文件保护:icacls "C:\pg\15\slave\standby.signal" /deny Administrators:F,禁止任何人修改。高可用,始于敬畏细节。