PostgreSQL 锁监控:先找阻塞链,再决定处理方式

背景 被阻塞的 SQL 不一定是罪魁祸首,真正的阻塞者可能已经 idle in transaction。排障要先还原阻塞链和事务年龄。 核心判断 用 pg_blocking_pids 获取阻塞者,再关联 pg_stat_activity。 同时观察 wait_event、xact_start 和应用名,判断锁等待来源。 先与业务方确认事务副作用,再决定取消语句或终止会话。 最小示例 下面保留核心逻辑;业务类型、调用入口和环境配置按项目补齐。 SELECT blocked.pid AS blocked_pid, blocker.pid AS blocking_pid, now() - blocker.xact_start AS blocking_xact_age, blocked.wait_event_type, blocked.wait_event, blocked.query AS blocked_query, blocker.query AS blocking_query FROM pg_stat_activity AS blocked CROSS JOIN LATERAL unnest(pg_blocking_pids(blocked.pid)) AS p(pid) JOIN pg_stat_activity AS blocker ON blocker.pid = p.pid ORDER BY blocking_xact_age DESC NULLS LAST; 边界与误区 仅按 locktype 连接 pg_locks 会错误关联不同锁对象。示例使用官方阻塞关系函数;高频查询也有开销,诊断权限与采样频率应受控。 验证方式 建立一个长事务持锁,再让第二个连接等待,核对阻塞 PID 与 SQL。确认取消当前语句和结束整个会话的风险不同,不自动执行终止命令。 小结 监控阻塞者、被阻塞者、事务年龄和 SQL,区分长事务、DDL 与业务冲突。

2026年9月29日 · 1 分钟 · BvBeJ

Linux 文件描述符泄漏:从增长曲线定位资源所有权

背景 FD 用量不断上升,最终表现可能是无法建立连接,也可能是日志写入失败。需要先分清增长的是文件、socket 还是管道。 核心判断 按时间采集数量和符号链接目标,区分正常连接池与泄漏。 沿着打开、移交、关闭三个动作检查资源所有者。 重点覆盖错误分支、重试循环和提前返回。 最小示例 下面保留核心逻辑;业务类型、调用入口和环境配置按项目补齐。 pid=$(pidof app); printf 'total='; find "/proc/$pid/fd" -mindepth 1 -maxdepth 1 | wc -l; ls -l "/proc/$pid/fd" | head 边界与误区 提高 ulimit 只延迟触顶,不能修复泄漏。短暂连接峰值也不是泄漏证据,必须与请求量和回收过程对照。 验证方式 固定负载运行一段时间再停止,确认 FD 回落。采集 /proc 需要相应权限,示例的 pidof 单实例假设在多进程环境应改成逐 PID 处理。 小结 按进程统计 FD 总数和目标类型,沿着增长曲线寻找没有闭合的资源生命周期。

2026年9月17日 · 1 分钟 · BvBeJ

Linux 进程基线:先建立正常画像,再判断异常

背景 线程数从几十变成几百是否异常,取决于请求量和运行阶段。没有正常基线,排障很容易只盯着某个绝对值。 核心判断 按同一进程版本记录 RSS、线程、FD、连接数与请求负载。 区分预热增长、稳定平台和持续线性增长。 采样时记录 PID 与启动时间,进程重启后不要拼接成一条曲线。 最小示例 下面保留核心逻辑;业务类型、调用入口和环境配置按项目补齐。 pid=$(pidof app); ps -o pid,ppid,stat,%cpu,%mem,rss,nlwp,etime -p "$pid"; ls "/proc/$pid/fd" | wc -l 边界与误区 pidof 可能返回多个 PID,示例适用于单实例进程;多实例请逐个采样。RSS 增加也可能是缓存增长,不能单凭它认定泄漏。 验证方式 保留空载、稳定负载和峰值三个阶段的快照。停止压测后观察资源是否回到可解释的平台,再决定是否进一步抓堆或分析 FD。 小结 围绕进程树、线程数、文件描述符、RSS 和连接数建立可比较的时间序列基线。

2026年9月7日 · 1 分钟 · BvBeJ