操作手册 · 数据库与存储

待环境验证

PostgreSQL 复制与高可用故障只读诊断

核对 PostgreSQL 主备角色、WAL 发送接收回放、复制槽与 Patroni 视图,区分复制故障、监控误读和高可用控制面异常。

PostgreSQL监控告警高可用
阅读导引 · 理解后再操作

这篇知识解决什么问题

本篇重点是判断数据库数据面、角色协调与业务入口是否在同一时间指向一致事实。先确认实例和时间线,再用连续采样解释发送、接收与回放差异;只读证据用于收窄问题,不作为提升节点、修改路由或宣告零数据丢失的授权。

判断角色需要多层一致证据

数据库恢复状态、控制面的领导角色和代理后端属于不同观察层,任何单层都可能尚未反映合法切换后的新状态。先对齐采样时间与实例标识,再检查既有角色、入口及隔离记录;发生矛盾时保留疑似分叉状态,而不是挑选最符合预期的一张截图。

进度必须带上负载和时间线

位置变化描述 WAL 推进,时间戳描述最近事务记录,两者不能直接互换成业务延迟。主库空闲、统计快照或归档恢复都可能改变读数含义;只有同集群、可比较时间线和相近采样窗口的趋势,才能支持对传输或回放瓶颈的进一步判断。

进入文章正文
关联架构图解8 个组件 · 点击展开

借用场景图观察 WAL 数据流、Patroni/etcd 协调和 HAProxy 入口的三层关系。图中成员组为逻辑聚合,不展示真实故障域、同步参数、旧连接和全部隔离路径,不能据图确认现场已具备可靠切换能力。

查看场景架构与实施步骤
参考架构 · 非实时拓扑

WAL 复制、DCS 租约与写入口隔离架构

PostgreSQL 主副本传递 WAL,节点本地 Patroni 经 etcd 协调角色,HAProxy 查询主角色接口路由新连接;可靠旧主隔离与独立备份分别保护写入和恢复。

  • 数据 / 请求
  • 控制 / 管理
  • 观测 / 查询

点击组件,在图下方查看职责;连线编号对应流向解读。小屏可横向滚动,或直接展开文字说明。

WAL 复制、DCS 租约与写入口隔离架构:组件关系图PostgreSQL 主副本传递 WAL,节点本地 Patroni 经 etcd 协调角色,HAProxy 查询主角色接口路由新连接;可靠旧主隔离与独立备份分别保护写入和恢复。 应用连接池 → HAProxy:业务连接;HAProxy → PostgreSQL 主库:转发当前主连接;PostgreSQL 主库 → PostgreSQL 副本:WAL 流复制;节点本地 Patroni → etcd DCS 组:租约与协调读写;节点本地 Patroni → PostgreSQL 主库:受约束管理角色;HAProxy → 节点本地 Patroni:探测 /primary;节点本地 Patroni → watchdog / 隔离:隔离安全前提;watchdog / 隔离 → PostgreSQL 主库:阻止失权旧主写入;PostgreSQL 副本 → 独立备份与恢复:经核验的备份路径。箭头说明见下方流向解读。
逻辑参考图,Patroni 表示每台数据节点上的进程,etcd 与副本按逻辑组聚合;不代表真实自动切换、隔离或备份恢复已经验收。

应用连接池

入口 / 来源

使用已有冗余代理入口,处理旧长连接和提交结果未知的事务;不能无条件重放所有写请求。

全部组件职责 8 个组件
应用连接池
使用已有冗余代理入口,处理旧长连接和提交结果未知的事务;不能无条件重放所有写请求。
HAProxy
依据 Patroni 主角色健康端点选择写后端,代理自身需已有冗余入口;数据库端口存活不足以证明可写角色。工具介绍 HAProxy
etcd DCS 组
保存协调状态与领导租约,成员通信和磁盘健康影响多数可用性;etcd 多数不是 PostgreSQL 数据复制多数。工具介绍 etcd DCS 组
节点本地 Patroni
每台数据节点分别运行 Patroni,本节点按 DCS 租约及复制约束管理 PostgreSQL。图中聚合展示,不是中央单实例控制器。工具介绍 节点本地 Patroni
PostgreSQL 主库
承接写事务并输出 WAL。复制模式与事务参数决定实际一致性边界,不能因 DCS 健康就承诺零丢失。工具介绍 PostgreSQL 主库
watchdog / 隔离
采用经过目标环境验证的 watchdog 或外部 fencing,明确租约丢失、进程卡死和网络隔离时的阻写责任与恢复通道。
独立备份与恢复
保存独立恢复所需基础备份与 WAL,并在隔离环境核对。图示从合格副本取备份为可选路径,需要验证其配置和完整性。
PostgreSQL 副本
持续接收与回放 WAL,候选资格需核对滞后、时间线和同步配置;本场景主库与两副本分别运行 Patroni。工具介绍 PostgreSQL 副本
流向解读 9 条连接
  1. 1

    应用连接池 HAProxy

    数据 / 请求 · 业务连接

    应用经已有冗余入口发送请求,角色变化时需重建失效连接并核对不确定事务。

  2. 2

    HAProxy PostgreSQL 主库

    数据 / 请求 · 转发当前主连接

    写后端仅选择经角色检查确认的主节点,不能把健康端口中的所有数据库都当作可写后端。

  3. 3

    PostgreSQL 主库 PostgreSQL 副本

    数据 / 请求 · WAL 流复制

    WAL 从主库传到副本;同步模式和提交设置需分别评审,图示复制方向不表示所有事务已经同步确认。

  4. 4

    节点本地 Patroni etcd DCS 组

    控制 / 管理 · 租约与协调读写

    各节点 Patroni 访问 DCS 维护角色协调信息,DCS 多数丢失的降级策略必须先定义。

  5. 5

    节点本地 Patroni PostgreSQL 主库

    控制 / 管理 · 受约束管理角色

    节点本地 Patroni 按有效租约、复制资格及隔离要求管理角色;图中同类本地控制也存在于副本节点。

  6. 6

    HAProxy 节点本地 Patroni

    观测 / 查询 · 探测 /primary

    代理请求各节点 Patroni 的 /primary 等主角色健康端点,要求数据库为主且持有领导锁,不用 /health 代替角色判断。

  7. 7

    节点本地 Patroni watchdog / 隔离

    控制 / 管理 · 隔离安全前提

    表示配置并验证 watchdog 或外部隔离职责;外部 fencing 的执行方取决于实际方案,不默认 Patroni 内置所有隔离能力。

  8. 8

    watchdog / 隔离 PostgreSQL 主库

    控制 / 管理 · 阻止失权旧主写入

    失去领导资格时,旧节点必须无法继续通过直连或旧连接接写,代理摘除不能独自提供该保证。

  9. 9

    PostgreSQL 副本 独立备份与恢复

    数据 / 请求 · 经核验的备份路径

    可从满足备份条件的副本取基础备份,并确保所需 WAL 完整;也可按原方案选择主库,必须独立恢复校验。

故障域与操作边界

DCS 多数与数据提交不是一回事

etcd 多数用于角色协调;默认异步复制仍可能丢失已确认事务,同步 strict 模式也可能因缺少同步副本阻塞写入。

代理摘除不能代替可靠隔离

旧长连接或直连可能绕过代理。失权旧主的阻写、watchdog 可用性与外部 fencing 必须在提升前按实际方案验证。

时间线分叉不能直接自动回切

旧主重新加入前保留 WAL 与事务证据,按可信主库重同步;高可用副本不能代替独立备份或跨地域恢复验证。

架构依据与版本核对 5 篇官方资料

图解是本站基于官方资料整理的逻辑参考;实施前仍需核对实际部署版本、组件支持范围与变更审批。

适用范围与版本边界

本文面向 PostgreSQL 物理流复制,并补充使用 Patroni、etcd 与 HAProxy 时的高可用视图核对。SQL 按 PostgreSQL 17 文档编写;其他版本先核对视图字段与函数权限,逻辑复制订阅不适用这套主备进度判据。Patroni 输出随版本变化,应记录实际版本和集群配置。本文没有执行提升、切换、重建或数据写入,验证状态为待验证。

前提:连接到可识别的实例

准备主库、每个备库及业务代理入口的映射,使用已授予必要监控读取权限的账号。部分统计字段对普通账号不可见,缺失或 NULL 可能是权限原因;不要临时授予超级用户来完成诊断。凭据使用现有连接服务或受控凭据存储,禁止在工单中暴露连接密码、复制连接串或完整配置文件。

SQL 片段应分别在已确认的目标实例运行,使用短时只读事务和查询超时,及时结束事务;例如在当前诊断连接先执行 BEGIN READ ONLY;SET LOCAL statement_timeout = '5s';,完成一轮读取后 COMMIT;。重新采样开启新事务,避免长事务和统计快照造成误读。事务设置仅影响该诊断会话,不替代账号权限控制。

第一步:核对数据库角色与入口

SELECT clock_timestamp() AS sampled_at,
       current_setting('server_version') AS server_version,
       inet_server_addr() AS server_addr,
       inet_server_port() AS server_port,
       pg_is_in_recovery() AS in_recovery;

分别记录直连每个实例与通过业务入口的结果。in_recovery=true 说明仍在恢复,false 不单独证明该实例被批准承接业务写入;还需要控制面、网络隔离和路由证据。代理、连接池和 Unix socket 可能使地址字段不能直接对应资产,必要时由平台的现有实例标识补齐。

同一 HA 集群中若出现两个都自认为可承接主库职责的节点,立即按疑似双主升级,不通过写入测试决定“谁才是真的主库”。只读核对角色时也要记录采样先后,因为正在进行的合法切换可能使相邻时刻不同。

第二步:在主库看 WAL 发送链路

确认该连接是预期主库后读取:

SELECT application_name, client_addr, state, sync_state,
       sent_lsn, write_lsn, flush_lsn, replay_lsn,
       write_lag, flush_lag, replay_lag, reply_time
FROM pg_stat_replication
ORDER BY application_name;

SELECT pg_current_wal_lsn() AS primary_lsn;

将每行连接与预期备库映射,区分连接不存在、仍在追赶和稳定流式传输。sync_state 应与设计的同步策略比对;仅看到一个同步状态不能直接推出完整的零数据丢失保证。延迟字段描述近期 WAL 的发送反馈过程,不是预测追平所需时间;空闲或追平后可能变成 NULL,不能因此认定复制断开。PostgreSQL 统计文档 给出这些字段的含义。

若备库连接缺失,先核对备库进程状态、认证与连接日志、网络和 WAL 可用性;日志只截取相关时间段并脱敏。不通过创建新的复制连接或重启来替代证据收集。

第三步:在备库分离接收与回放

SELECT status, sender_host, sender_port, slot_name,
       flushed_lsn, received_tli,
       last_msg_send_time, last_msg_receipt_time
FROM pg_stat_wal_receiver;

SELECT pg_last_wal_receive_lsn() AS receive_lsn,
       pg_last_wal_replay_lsn() AS replay_lsn,
       pg_last_xact_replay_timestamp() AS last_replayed_xact,
       pg_is_wal_replay_paused() AS replay_paused;

先确认实例仍处于恢复;若角色已变,停止套用备库判据并重新建立拓扑。接收位置持续前进但回放位置停滞,关注恢复暂停、备库 IO、CPU 与查询冲突;接收和回放都不动时,需要先证明主库仍产生 WAL,再调查上游传输。接收器没有行也可能正在使用归档恢复,不能仅凭空视图判定没有任何恢复路径。

pg_last_xact_replay_timestamp() 是最后回放事务在主库产生提交或中止记录的时间,主库没有新事务时,其距当前时间可以不断增大;这不是可靠的独立复制延迟告警。恢复信息函数 说明各位置与时间戳的边界。

第四步:计算有上下文的进度差

在同一备库可用下面的只读表达式观察已接收但尚未回放的 WAL 字节差:

SELECT pg_wal_lsn_diff(pg_last_wal_receive_lsn(),
                       pg_last_wal_replay_lsn()) AS receive_replay_gap_bytes;

NULL 应保留为未知,不强制替换成零。比较主库当前位置与备库位置前,必须确认属于同一集群和兼容的时间线,且采样时间接近;跨时间线或切换前后的位置不能草率相减。差值是 WAL 字节差,不是事务数,不一定包含所有业务延迟来源。至少对比两个时间点与业务负载,避免单点误判。

出现负值或与拓扑不一致时,先检查采样来源、归档与流复制路径、角色变化和时间线,不据此做提升决定。异步复制存在故障时未复制事务丢失的边界,必须按照业务允许的 RPO 和实际证据评估,而不是看到“streaming”就认定安全。主备复制指南 说明同步与异步复制语义。

第五步:核对复制槽与 WAL 容量风险

在预期主库上只读取物理槽:

SELECT slot_name, slot_type, active, restart_lsn,
       wal_status, safe_wal_size
FROM pg_replication_slots
WHERE slot_type = 'physical'
ORDER BY slot_name;

将槽名与配置中的备库用途对应,结合既有磁盘监控观察 WAL 目录增长。非活跃槽不能直接判为可删:备库离线、临时维护或控制面管理都可能解释它。wal_statussafe_wal_size 需要按保留上限和状态解读,NULL 不统一表示容量充足;相关定义见 pg_replication_slots

如果所需 WAL 已不可用,需要由负责人评估归档恢复或重建,而不是删除槽后假设复制能继续。诊断中不删除或推进复制槽、不删除 WAL 文件,也不修改 WAL 保留策略。

第六步:对照 Patroni、DCS 与代理

仅在使用 Patroni 的环境,利用已授权的配置和具体集群名读取:

OPS_PATRONI_CONFIG='/REPLACE_WITH_APPROVED_PATRONI_CONFIG'
OPS_PATRONI_CLUSTER='REPLACE_WITH_CLUSTER_NAME'
patronictl -c "$OPS_PATRONI_CONFIG" list "$OPS_PATRONI_CLUSTER" --extended

核对成员、角色、时间线、状态和待重启提示与 SQL 观测是否一致;Patroni 的列表不是独立的写入隔离证明。patronictl 文档 列出输出字段与命令用途。再通过已有只读监控核对 etcd 仲裁与连接错误、Patroni 日志及 HAProxy 后端状态,不临时修改 DCS key、代理路由或健康检查。

数据库正常但 DCS 失联、代理仍指向旧主、SQL 角色与控制面矛盾,应分别记录并升级。特别是疑似双主时,写入隔离必须由事故负责人按既定机制执行,本手册不自动选择或提升任何候选节点。

验收、停止与恢复边界

验收应说明主备映射一致、接收与回放趋势可解释、槽和 WAL 容量风险受控、控制面与业务入口一致,并在业务认可的只读查询中确认可见性。恢复后持续观察一个约定业务窗口,不能只以连接成功或单次 Lag 为零结案。

出现疑似双主、持续 WAL 丢失错误、磁盘接近耗尽或查询影响业务,停止扩大采样并升级处置。严禁在此流程执行 pg_promote、Patroni failover/switchover、reinit、修改同步策略或清理数据目录。只读诊断无数据回滚;新主接受写入后,返回旧主不是简单切回地址,必须先处理分叉、隔离和数据一致性。

案例证据记录模板

  • 事件编号、PostgreSQL/Patroni 版本、集群与实例映射、连接入口:待填。
  • 每次采样时间、角色、时间线、发送/接收/回放位置及解释:待填。
  • 复制连接、槽、WAL 容量、DCS 与代理证据:待填。
  • 业务可见性、RPO/RTO 要求、疑似分叉或丢失范围:待填。
  • 假设与反证、授权负责人、停止条件、复查结果:待填。

示例不表示已经达到 RPO/RTO,不把未测量的数据保护能力写成验收事实。

相关站内内容

参考资料

从现象到判断

先收集证据,再缩小范围。以下是判读路径,不代表已经确认根因或获准变更。

  1. 备库最后事务时间越来越旧,但业务没有明确新增写入证据,单张延迟看板持续上升。

    只读核对
    只读对照两个时间点的主库 WAL 位置、备库接收与回放位置,并审阅同窗口既有业务写入趋势。
    如何判读
    若主库没有推进,旧事务时间不能独立证明复制积压;仍需核对连接、角色和采样权限是否一致。
  2. 备库接收位置持续前进而回放位置滞留,同期读取请求变慢,但复制连接仍显示存在。

    只读核对
    读取已批准的恢复暂停状态与复制视图,结合既有磁盘、CPU 和查询冲突记录核对相同实例及时间窗。
    如何判读
    现象把候选范围收窄到回放侧,暂停、资源压力或查询冲突仍需分别排除,不能直接决定提升。
  3. SQL 显示实例不在恢复中,但 Patroni 角色或业务代理后端仍与它不一致,且存在旧连接。

    只读核对
    只读保存各实例身份、控制面列表、代理状态及近期切换日志,核对采样先后和既有写入隔离证据。
    如何判读
    可能是合法切换传播差异,也可能是危险角色冲突;没有一致时间线与隔离证明前维持升级处理。
常见误区与判断边界 2 项

把空值和空视图统一补成零

统计字段不可见、空闲后的延迟空值和归档恢复时缺少接收器记录具有不同含义。补零会把未知状态变成健康结论,也使后续无法复查证据缺口。应记录权限、角色及数据来源,再由对应视图的版本语义解释,而非扩大账号权限凑齐字段。

以代理摘除代替旧主隔离

代理主要影响经它建立的新连接,已有长连接或直连路径仍需要单独证据。发现路由已变不能宣布旧主失去写能力,更不能用一次生产写入测试选主;旧主重新加入也涉及时间线和数据差异,应交由既定事故与恢复流程决定。

交接时应留下的证据

作为记录提纲使用,不是自动检查结果;未取得的证据应标记缺口,并注明负责人。

  • 保存主库、各备库与业务入口的别名映射、版本和采样时区,注明代理或连接池导致地址无法直接对应的项目。
  • 保留至少两个时间点的发送、接收与回放位置,以及同窗口主库写入趋势、时间线和未知字段的原因说明。
  • 关联复制连接、物理槽、WAL 容量、Patroni 与代理状态的脱敏附件,记录角色冲突是否已排除和复核责任人。
  • 交接每项根因假设的支持与反证、只读业务可见性、停止条件及尚未验证范围,不把可连接写成恢复已完成。

记录需包含环境、版本、时间与时区;分享前脱敏,不附访问令牌、密码或完整业务敏感数据。

继续阅读与资料核对

补充相关主题,再结合当前环境的实施记录形成结论。

返回原理导读

DOUYA OPS ECOSYSTEM

贡献你的经验,帮助更多运维人

把故障复盘、标准流程和最佳实践沉淀为可检索、可复用的知识内容。