34.1 第一动作:流量型还是保留型
资源告警出现后,先不要问“删什么”或“重启谁”,而要问:
当前资源是被正在到达和执行的工作消耗,还是被一个不能前进的历史边界 保留?
这不是给故障贴标签,而是选择安全动作。流量型压力需要减少进入量、并发或单项成本; 保留型压力需要找到保留者及其 owner。两类证据都成立时,先处理即将触发的硬失败, 同时保留另一条根因链;两类都不成立时,保持 unknown。
34.1.1 流量增长、慢查询、锁与连接导致的竞争
流量型的共同结构
下面四种表象最后都会形成“到达大于完成”:
| 放大源 | 到达侧变化 | 完成侧变化 |
|---|---|---|
| 业务流量增长 | 请求数增加 | 单次成本可能不变 |
| 慢查询或坏计划 | 请求数不变 | 每次占用 CPU/I/O/连接更久 |
| 锁竞争 | 等待工作继续占连接 | 有效并行度下降 |
| 连接风暴 | 建连、认证、backend 创建增加 | 正常查询拿不到 admission |
若每秒进入 $\lambda$ 个工作、完成 $\mu$ 个工作,持续满足 $\lambda>\mu$,队列就增长。 这里的工作可以是 HTTP 请求、池等待者、数据库 session、正在运行的 statement 或磁盘 I/O。只看 PostgreSQL 的 active session 会漏掉在应用池和代理前排队的请求。
先把同一 UTC 窗口的证据放在一起:
再对照:
state='active' 不表示正在使用 CPU;PostgreSQL 文档明确指出 state 与 wait_event
相互独立。active 且 wait_event_type='Lock' 的 backend 正在执行语句,但实际被阻塞。
这也是为什么“active 数很多”必须继续拆成 running、lock wait、I/O wait 与 client wait。
判定成立的最低条件
把问题判为 flow,至少应看到一条能够闭合的因果链:
仅凭 CPU 90% 不够。CPU 高也可能是 checkpoint 后的恢复工作、压缩、备份或一个与用户 延迟无关的后台任务;连接数高也可能都是长期 idle、但尚未达到瓶颈。
34.1.2 WAL、XID、复制槽、归档和长事务导致的保留
保留型不是“有人正在大量使用”
PostgreSQL 为恢复、复制和 MVCC 正确性保留历史。只要某个消费者仍声明“我可能需要 这里以前的内容”,系统就不能越过它回收:
| 被保留对象 | 常见保留者 | 关键边界 |
|---|---|---|
| 旧 tuple 版本 | 活跃快照、长事务、prepared transaction | backend_xmin、prepared XID |
| catalog tuple | logical replication slot | catalog_xmin |
| WAL segment | physical/logical slot、备库、备份 | restart_lsn |
| 待归档 WAL | archive command/repository 失败 | pg_stat_archiver 与归档队列 |
| 事务 ID 安全空间 | 未冻结表与被钉住的 xmin | relation/database age |
这里重要的是最老边界及其速度:
inactive slot 不等于废弃 slot。它可能对应暂时离线的副本、迁移、CDC 消费者或恢复流程; active slot 也不等于健康,消费者可能连着却不推进。必须把 slot 映射到服务 owner、 consumer、恢复承诺和最后成功时间。
先测增长,再谈释放
两个快照比一个快照更有意义:
若 max_slot_wal_keep_size=-1,replication slot 可以不受该参数上限地保留 WAL;即使配置
了有限值,相关状态也在 checkpoint 时才重新评估,不能把参数值误当作实时保险丝。
34.1.3 同样表现为“磁盘满”或“延迟高”,动作可以相反
症状相同,控制变量不同
| 症状 | 可能的 flow 根因 | 可能的 retention 根因 | 需要区分的证据 |
|---|---|---|---|
pg_wal 大 |
写流量突增、checkpoint 压力 | slot/归档/备份钉住 WAL | WAL 生成率与最老保留 LSN |
| 表膨胀 | 更新/删除量增长 | 长快照或 slot catalog_xmin |
DML 率、vacuum 进度与 xmin |
| 磁盘延迟高 | 并发查询、temp、checkpoint | 被保留数据持续占满并触发写放大 | device queue、文件分类、增长率 |
| 连接失败 | 到达/重试超过连接预算 | 磁盘满后新事务无法写 WAL | pool queue、PG error、filesystem |
| CPU 高 | 执行/解析/自旋竞争 | recovery/cleanup 追赶保留积压 | backend type、wait、工作量变化 |
因此动作可以完全相反:
把 retention 当 flow,取消再多普通查询也不会推进 restart_lsn。把 flow 当 retention,
忙着调查 slot 而不限制重试,服务可能先被连接和内存击穿。
同时发生怎么办
WAL slot 滞留期间又发生写入洪峰并不矛盾。事故记录应允许:
“只能选一个根因”是复盘分类,不是在线处理原则。
34.1.4 判型不清时先停止破坏性清理
unknown 是一种有效状态
下面任一项不明,就不能执行不可逆释放:
先收集最小证据包:
然后将路线写成机器与人都能审阅的三态判定:
停止线包括:有人建议删 pg_wal、drop 未知 slot、终止未知大事务、在唯一副本上试验
危险参数、或以“磁盘快满”为由跳过 owner/backup 识别。此时应保护现场并回到第 31 章
的事故指挥框架。
本节交付物
进入具体止血前,至少写出:
没有这些字段,“先重启看看”不是 runbook。
返回本章目录 · 下一节:连接风暴与排队失控 · 查看全书目录 · 查看索引中心