Postgres - 如何调试/跟踪'Idle in transaction'连接



我正在为我的一个应用程序使用 Postgres,有时(不是很频繁)其中一个连接进入<IDLE> in transaction状态,它保持获取的锁,导致其他连接等待这些锁,最终导致我的应用程序挂起。

以下是该进程pg_stat_activity表的输出:

select * from pg_stat_activity
24081 | db     |     798 |    16384 | db     |                  | 10.112.61.218 |                 |       59034 | 2013-09-12 23:46:05.132267+00 | 2013-09-12 23:47:31.763084+00 | 2013-09-12 23:47:31.763534+00 | f       | <IDLE> in transaction

这表示PID=798处于<IDLE> in transaction状态。Web服务器上的客户端进程如下,使用上述输出中的client_port59034)。

sudo netstat -apl | grep 59034
tcp        0      0 ip-10-112-61-218.:59034 db-server:postgresql    ESTABLISHED 23843/pgbouncer

我知道我的应用程序代码中出了点问题(我杀死了一个正在运行的应用程序 cron 并释放了锁),导致连接挂起,但我无法跟踪它。

这不是很常见,我也找不到任何明确的复制步骤,因为这只发生在生产服务器上。

我想获得有关如何跟踪此类空闲连接的输入,例如获取上次执行的查询或某种回溯以确定导致此问题的代码部分。

如果升级到 9.2 或更高版本,pg_stat_activity视图将显示最近对idle in transaction连接执行的查询。

select * from pg_stat_activity  xgx
...
waiting          | f
state            | idle in transaction
query            | select count(*) from pg_class ;

您还可以(即使在 9.1 中)查看pg_locks以查看idle in transaction进程持有哪些锁。 如果它只在非常常用的对象上具有锁,这可能不会缩小范围,但如果它是一个特殊的锁,可以准确地告诉您在代码中查找的位置。

如果您坚持使用 9.1,也许可以使用调试器获取查询的前 22 个字符以外的所有字符(前 22 个字符被 <IDLE> in transaction 消息覆盖)。 例如:

(gdb) printf "%sn", ((MyBEEntry->st_activity)+22)

最新更新