2. 生产环境应急响应流程

PostgreSQL 生产故障的应急响应,本质上不是“修数据库”,而是在信息不完整、时间压力大、业务持续受损的条件下,做出一系列可解释、可追溯、可回退的决策。告警响起时,DBA 面对的第一个问题往往不是“怎么修”,而是“这件事有多严重、谁需要知道、我能不能先动它”。因此,一套稳定的响应流程必须把发现、评估、定级、沟通、决策五个环节串成闭环,并针对 PostgreSQL 的典型故障场景预置判断依据和动作清单。

一、告警发现:先分清“信号”与“噪声”

PostgreSQL 的告警来源通常有三类:监控系统(连接数、复制延迟、锁等待、长事务、磁盘使用率)、数据库自身日志(FATAL、PANIC、checkpoint 警告、autovacuum 失败)、以及业务侧反馈(接口超时、订单失败)。应急响应的第一步是快速判断告警是否指向真实故障,而不是把监控抖动当成事故。

一个实用的做法是建立“告警—指标—日志”三角验证:监控告警触发后,立即用只读查询确认当前状态,再对照日志时间线。例如连接数告警时,先执行:

SELECT count(*) AS total,
       count(*) FILTER (WHERE state = 'active') AS active,
       count(*) FILTER (WHERE wait_event_type = 'Lock') AS lock_wait
FROM pg_stat_activity;

如果 total 接近 max_connections,active 不高但 lock_wait 很高,说明问题更可能是锁阻塞而非连接泄漏;如果 active 高且大量会话处于 idle in transaction,则要优先排查应用事务未提交。这个判断直接决定后续定级和沟通对象。

PostgreSQL 生产应急响应决策链 ① 告警发现 监控 / 日志 / 业务反馈 三角验证:指标+日志+查询 排除噪声,确认真实故障 ② 影响评估 业务受损面 / 数据风险 是否可读写 / 是否丢数据 影响用户量与持续时间 ③ 故障定级 P0 全站不可用 P1 核心功能受损 P2 局部降级 / P3 观察 ④ 沟通机制 定级决定通知范围 统一信息出口 定期同步进展 ⑤ 恢复决策 先止损(限流/切只读/杀阻塞)→ 再恢复(重启/切换/回滚) 每一步保留回退路径,记录操作时间线 PostgreSQL 典型故障场景与首查动作 连接耗尽 / 会话堆积 查 pg_stat_activity 识别 idle in transaction 必要时终止异常会话 风险:误杀关键事务 锁等待 / 长事务阻塞 查 pg_locks + pg_stat_activity 定位阻塞源头 PID 评估是否可安全取消 风险:取消引发回滚风暴 复制延迟 / 主备切换 查 pg_stat_replication 确认延迟字节与时间 评估切换的数据丢失窗口 风险:脑裂 / 数据不一致 磁盘满 / WAL 堆积 查 df -h 与 pg_wal 大小 确认归档是否失败 清理或扩容,恢复归档 风险:数据库只读/崩溃

二、影响评估:把“数据库状态”翻译成“业务损失”

影响评估的核心是把技术指标映射到业务后果。同样是主库不可写,订单库和报表库的定级完全不同。评估时至少回答四个问题:哪些业务功能不可用、是否影响数据正确性、受影响用户规模多大、预计持续多久。其中“是否影响数据正确性”优先级最高——如果故障可能导致数据丢失或错乱,即使业务还能读,也应直接提升定级。

以主库磁盘满为例,PostgreSQL 在 WAL 无法写入时会进入只读甚至拒绝连接状态。此时评估要点是:只读是否影响下单、支付等写路径;从库是否还能提供读服务;归档中断后 WAL 堆积速度多快。假设监控显示 pg_wal 目录 30 分钟内从 20GB 涨到 45GB,磁盘剩余 8GB,那么即使当前业务只是“部分写失败”,也应按 P1 处理,因为数据库随时可能完全不可用。

三、故障定级:用可执行的判据代替感觉

定级不是给故障贴标签,而是决定资源投入和通知范围。建议用一张简明的判据表,把定级条件写死,避免现场争论。以下为示例判据,实际使用时需结合业务 SLA 调整:

级别判据(满足其一)通知范围响应要求
P0主库不可连接;数据确认丢失;全站写失败技术负责人、业务负责人、管理层立即全员响应,15 分钟同步一次
P1核心写路径失败;复制中断且延迟持续扩大;磁盘剩余不足 10%DBA、研发负责人、业务接口人30 分钟内给出止损方案
P2非核心功能降级;只读延迟明显;单节点故障但已切换DBA、值班研发1 小时内处理,按需升级
P3指标异常但业务无感知;可观察的慢查询增多值班 DBA记录并跟踪,无需即时通知

定级后要立即明确一个现场指挥角色,通常由资深 DBA 或技术负责人担任,负责决策而非亲自敲命令。这个角色要持续回答三个问题:当前止损动作是什么、下一步动作的触发条件是什么、如果动作失败回退路径是什么。

四、沟通机制:统一出口,减少信息噪声

故障期间最忌讳多头指挥和碎片化沟通。建议约定一个主沟通渠道(如应急群),并固定信息模板:当前级别、影响范围、已执行动作、当前数据库状态、下一步计划、下次同步时间。对外(业务方)只同步影响和预计恢复时间,不展开技术细节;对内(技术团队)同步操作指令和验证结果。

沟通节奏建议:P0 每 15 分钟同步一次,P1 每 30 分钟一次,P2 每 1 小时一次。每次同步必须包含“相比上次有什么变化”,避免重复播报同一状态。

五、恢复决策:先止损,再恢复,保留回退

恢复决策的顺序应当是:先止血,再治病,最后复盘。止血动作包括限流、切只读、终止阻塞会话、暂停非关键批处理;治病动作包括重启实例、主备切换、清理 WAL、扩容磁盘、回滚变更。每一步都要有明确的验证点,例如终止阻塞会话后,立即确认锁等待是否下降、业务写是否恢复。

以主备切换为例,决策前必须确认:从库延迟是否在可接受范围(例如小于 10MB 或 30 秒)、切换后应用连接串是否已更新、旧主是否已隔离防止脑裂。切换后要验证:新主可写、复制关系重建、业务关键接口成功率恢复。如果切换后业务仍失败,应优先回退到原主(若原主仍可用),而不是继续叠加变更。

恢复决策的底线:任何可能造成数据丢失的操作(如强制切换、跳过 WAL、重建从库)都必须先确认备份可用性和恢复点目标(RPO),并留下书面记录。宁可多花 5 分钟确认,也不要在数据风险上赌运气。

六、响应清单:把流程变成可执行动作

以下清单可直接作为值班 DBA 的应急卡片,按顺序执行,每完成一项打勾并记录时间:

  1. 确认告警真实性:查监控面板、查 pg_stat_activity、查数据库日志最近 50 行,排除监控误报。
  2. 判断影响面:确认主库是否可写、从库是否可读、核心业务接口成功率、受影响用户量级。
  3. 定级并通知:按判据表定级,在应急群发布第一条状态,明确指挥人和下次同步时间。
  4. 执行止损:根据场景选择限流、切只读、终止阻塞会话、暂停批处理等动作,每步验证效果。
  5. 评估恢复方案:列出可选方案(重启、切换、扩容、回滚),评估每个方案的数据风险和预计耗时。
  6. 执行恢复并验证:按选定方案操作,验证数据库可写、复制正常、业务接口恢复。
  7. 记录时间线:从告警时间到恢复时间,记录每个关键动作和观察结果,为复盘提供依据。
  8. 降级与收尾:确认稳定后降级通知,保留监控观察窗口,安排复盘会议。

这套流程的价值不在于步骤本身,而在于它把“现场判断”变成了“可复用决策”。PostgreSQL 的故障场景虽然多样,但告警发现、影响评估、定级、沟通、恢复决策这五个环节是稳定的骨架。真正需要演练的,是在每个环节中快速找到正确的查询、正确的判据和正确的回退路径。