[Eval][v3][zh] Payment service connection pool exhaustion after batch job deploy
service: payment-svccreated: 6/2/2026, 11:50:48 PM
Raw incident context
Time: 14:02 UTC. payment-svc p99 latency jumped from 120ms to 4.8s within ~3 minutes. Error rate climbed from 0.1% to 12% (mostly HTTP 500). Application logs (last 5min): repeated "FATAL: sorry, too many clients already" and "connection refused" from payment-svc → postgres-primary. Postgres metrics: - CPU: 35% (normal) - active_connections: 500 / 500 (max_connections) - waiting_queries: 87 - slow_query_log shows a new query running every 30s: SELECT * FROM ledger_entries WHERE status='pending' (no index on status; full table scan over ~12M rows, ~2.4s per execution) Deploy history: - 13:50 UTC — payment-svc v2.41 shipped. Changelog mentions "added nightly settlement batch (cron: */30 * * * *)" - No infra/DB changes in past 7 days. On-call notes (Slack): - 14:03 — CS reports failed checkout volume rising - 14:04 — Pager: PaymentSvcErrorRateHigh - 14:06 — "DB looks healthy, CPU is fine" (initial mis-diagnosis)
Summary
支付服务 payment-svc 在 14:02 UTC 出现 p99 延迟从 120ms 飙升到 4.8s,错误率从 0.1% 升至 12%(HTTP 500),客户报告结账失败。根本原因是新部署的 v2.41 引入了一个每 30 秒运行的全表扫描查询,耗尽了 PostgreSQL 的连接池(max_connections=500),导致其他查询被拒绝。
Severity reasoning: 用户可见的结账失败(错误率 >1% 超过 5 分钟),且影响收入路径。符合 SEV1 标准:用户面中断、错误率 >1% 超过 5 分钟、收入路径受损。
deepseek-chat·prompt v3·output: zh·11798ms·2401↑ / 1816↓ tok·$0.00265
Root cause hypotheses
- high新部署的 v2.41 引入的定时任务(cron: */30 * * * *)执行全表扫描查询 SELECT * FROM ledger_entries WHERE status='pending',该查询无索引,每次执行约 2.4 秒,占用了大量数据库连接,导致连接池耗尽。
Evidence: 应用日志显示 'FATAL: sorry, too many clients already' 和 'connection refused';Postgres 指标显示 active_connections=500/500,慢查询日志显示该查询每 30 秒运行一次。
- low数据库连接泄漏:应用代码未正确关闭连接,导致连接数持续增长直至耗尽。
Evidence: 连接数达到上限 500,但 CPU 正常(35%),慢查询日志中只有一条新查询,没有其他异常。连接泄漏通常伴随更多异常连接,但此处仅有一条新查询。
- medium外部流量突增导致正常查询量超过数据库处理能力。
Evidence: 错误率在 3 分钟内从 0.1% 升至 12%,但部署时间(13:50)与症状开始时间(14:02)吻合,且无其他流量异常报告。
Investigation checklist
- 确认连接池是否被慢查询耗尽
kubectl exec -n prod deployment/postgres-primary -- psql -U postgres -c "SELECT count(*) FROM pg_stat_activity WHERE state != 'idle';"Expected: 返回接近 500 的活跃连接数,确认连接池耗尽。
- 查看慢查询详情,确认全表扫描
kubectl exec -n prod deployment/postgres-primary -- psql -U postgres -c "SELECT query, calls, total_exec_time, rows, query_start FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 5;"Expected: 显示 SELECT * FROM ledger_entries WHERE status='pending' 总执行时间最高,且 rows 接近表行数(12M),确认无索引。
- 检查新部署的 cron 任务配置
kubectl logs -n prod -l app=payment-svc --since=30m | grep -i 'settlement\|batch\|cron' | head -20Expected: 显示每 30 秒执行一次 settlement batch 的日志条目。
- 检查数据库连接池配置
kubectl exec -n prod deployment/postgres-primary -- psql -U postgres -c "SHOW max_connections;"Expected: 显示 max_connections = 500。
- 检查是否有其他慢查询或锁竞争
kubectl exec -n prod deployment/postgres-primary -- psql -U postgres -c "SELECT pid, wait_event_type, wait_event, query FROM pg_stat_activity WHERE wait_event IS NOT NULL;"Expected: 大部分等待事件应为 'Client' 或空,无大量锁等待。
Mitigation plan
立即终止导致问题的慢查询,释放连接。
Risk: 终止查询可能导致该批次数据不一致,但影响有限(仅当前批次)。
Rollback: 无需回滚,查询已终止。
临时增加 max_connections 到 800(需重启数据库),以缓解连接压力。
Risk: 增加连接数可能增加内存使用,但当前 CPU 仅 35%,风险较低。重启数据库会导致短暂中断。
Rollback: 将 max_connections 改回 500 并重启。
回滚 payment-svc 到 v2.40,移除有问题的 cron 任务。
Risk: 回滚期间服务可能短暂不可用,但可快速恢复。
Rollback: 重新部署 v2.41(但需先修复问题)。
为 ledger_entries.status 创建索引,防止未来全表扫描。
Risk: 创建索引可能短暂锁表,但可在线创建(CONCURRENTLY)。
Rollback: 删除索引即可。
Customer impact
用户在进行结账时遇到失败,错误率约 12%,表现为页面超时或 500 错误。受影响用户比例约为 12% 的结账请求。预计在回滚和连接恢复后 10 分钟内解决。
Postmortem draft
摘要
[FILL IN: 2-3 句概述]
时间线 (UTC)
- 13:50 - payment-svc v2.41 部署,引入有问题的 cron 任务
- 14:02 - p99 延迟飙升,错误率上升
- 14:03 - CS 报告结账失败
- 14:04 - Pager 触发
- [FILL IN: 缓解时间]
影响
- 12% 的结账请求失败,持续约 [FILL IN] 分钟
- p99 延迟从 120ms 升至 4.8s
根因
新部署的 v2.41 引入了一个每 30 秒执行的全表扫描查询,耗尽了数据库连接池,导致正常查询被拒绝。
检测
Pager 告警 PaymentSvcErrorRateHigh 触发,但初始误判为数据库健康。
响应
- 14:06 - 初始误判
- [FILL IN: 实际缓解步骤]
做得好的
- 快速识别慢查询
- 回滚决策果断
做得不好的
- 代码审查未发现无索引查询
- 初始误判延迟了缓解
行动项
- [FILL IN: 具体行动项]
Follow-ups
- P0为 ledger_entries.status 添加索引,并验证查询性能。— 数据库管理员
- P1审查 payment-svc v2.41 的代码变更,确保 cron 任务不会导致类似问题。— 支付服务团队
- P1添加数据库连接池使用率的监控告警,阈值设为 80%。— 可观测性团队
- P2在部署流程中增加数据库查询审查步骤,特别是新引入的查询。— 平台工程团队
- P2更新 runbook,包含数据库连接耗尽时的快速诊断步骤。— SRE 值班团队
Similar past incidents
lexical match (pg_trgm)
- 76%
[Eval][v2][zh] Payment service connection pool exhaustion after batch job deploy
p99 latency 4.8s (up from 120ms), 12% 500 error rate, customers report failed checkouts
- 73%
[Eval][v1][zh] Payment service connection pool exhaustion after batch job deploy
p99 latency 4.8s (up from 120ms), 12% 500 error rate, customers report failed checkouts
- 46%
[Eval][v1][en] Payment service connection pool exhaustion after batch job deploy
p99 latency 4.8s (up from 120ms), 12% 500 error rate, customers report failed checkouts
- 46%
[Scenario] Payment service connection pool exhaustion after batch job deploy
p99 latency 4.8s (up from 120ms), 12% 500 error rate, customers report failed checkouts
- 45%
[Eval][v2][en] Payment service connection pool exhaustion after batch job deploy
p99 latency 4.8s (up from 120ms), 12% 500 error rate, customers report failed checkouts