PostgreSQL码农集散地

PG 连接被切断?5秒钟查出"凶手"

PostgreSQL 重磅更新:连接被切断?5秒钟查出"凶手"

一个 DBA 的深夜惊魂

凌晨2点,你被报警声吵醒。

生产数据库大量连接中断,错误日志清一色刷着"terminating connection due to administrator command"。你抓起手机开始排查:是运维同事在执行维护?还是监控脚本在清理空闲连接?或者——某位误操作的开发者闯了祸?

你翻遍日志,一头雾水。

"administrator command",哪个 administrator?谁的命令?

这个困扰 PostgreSQL DBA 多年的难题,终于有了官方解。


1. 发生了什么?

就在最近,PostgreSQL 社区合并了一个看似不起眼、却直击痛点的 commit(55890a9)。

它的名字叫信号溯源(Signal Source Attribution)。

翻译成人话就是:以后谁的连接被断了,数据库会明确告诉你——是哪个进程(PID)、哪个用户(UID)动的手。

看个对比:

改进前:

FATAL: terminating connection due to administrator command

——你知道被枪杀了,但不知道是谁开的枪。

改进后:

FATAL: terminating connection due to administrator command
DETAIL: Signal sent by PID 67890, UID 1005.

——枪号、射手,证据链完整。


2. 技术原理(3分钟看懂)

不想看代码的同学,直接跳到下一节。

PostgreSQL 底层用 SIGTERM 信号来终止后端连接。以往信号里只带着"我要杀你"的信息,但不告诉你谁发的。

这次改动利用了 Unix 的 SA_SIGINFO 扩展——这个能力可以让信号携带"发射者身份"。

简单说,信号里现在多了两个字段:

  • si_pid:发信号那个进程的 ID
  • si_uid:发信号那个进程所属用户的 ID

当后端进程被 SIGTERM 放倒时,日志就会多打印一行,明确告诉你"凶手"的 PID 和 UID。

支持哪些平台?

Linux、FreeBSD 等主流 Unix 系统都支持。Windows 用户暂时无缘这个功能(微软不给力)。


3. 三大真实场景

3.1 多 DBA 共管环境——谁动了我的连接?

场景还原:

公司数据库由 A、B 两个 DBA 团队共管,大家都用 pg_terminate_backend 权限。某天,某个核心业务的连接被误杀,业务方炸锅,两个团队互相甩锅。

有了信号溯源之后:

-- 查日志
DETAIL: Signal sent by PID 67890, UID 1005.

-- 顺着 PID 查进程
$ ps aux | grep 67890
# 定位到是一套监控脚本

-- 顺着 UID 查用户
$ id 1005
# 确认是 dba_user_zhang 在执行自动化巡检

30秒定责,锅甩得清清楚楚。


3.2 自动化运维——哪个工具在"捣鬼"?

很多公司用多套自动化工具管理 PostgreSQL:pgBadger 做分析、pgCluu 做审计、Patroni 做高可用……

某个后台会话突然被终止,日志只说"管理员命令",你得一个个工具去排查。

现在?

DETAIL: Signal sent by PID 31415, UID 0.

UID 为 0?说明是 root 或系统服务发起的。结合 systemd journal 直接定位是哪个服务,一分钟锁定目标。


3.3 Kubernetes 滚动更新——是 K8s 在升级,还是人为误删?

在 K8s 环境里,kubectl delete pod 会给容器发 SIGTERM。

以前日志看不出是滚动更新还是人为删除,现在一目了然:

DETAIL: Signal sent by PID 1, UID 0.

PID 1 在容器里通常是 init 进程(K8s 的 kubelet)。结合 K8s events,立刻能确认是滚动更新触发的正常重启,还是运维误操作。


4. 对 DBA 有多实用?

维度
改进前
改进后
故障定位时间
数小时,大海捞针
数分钟,直接命中
审计追溯
靠外部系统
PostgreSQL 日志自带
多租户环境
难以区分谁的锅
PID/UID 精确到人
自动化排查
盲人摸象
每个工具可溯源

5. 未来可期

这个功能目前只追踪 SIGTERM(即 pg_terminate_backend)。

社区已经在讨论扩展到:

  • pg_cancel_backend() 的溯源
  • 将 UID 转换为可读的用户名
  • pg_stat_activity 里增加信号来源字段

期待后续版本。


6. 写在最后

这个改动看似小,但解决的是一个高频痛点。

我见过太多 DBA 凌晨被报警叫醒,然后花几个小时在日志里"考古"——就为了回答一个问题:到底是谁干的?

现在,答案就在日志里。


你遇到过"连接被断却查不出凶手"的情况吗?欢迎留言聊聊你是怎么排查的。

觉得有用?转发给需要的朋友。