Postgres - 如何调试/跟踪'空闲事务'连接

时间:2013-09-13 15:05:53

标签: postgresql transactions

我正在为我的一个应用程序使用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状态。使用上面输出中的client_port59034)可以找到Web服务器上的客户端进程。

sudo netstat -apl | grep 59034

tcp        0      0 ip-10-112-61-218.:59034 db-server:postgresql    ESTABLISHED 23843/pgbouncer

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

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

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

1 个答案:

答案 0 :(得分:10)

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

select * from pg_stat_activity  \x\g\x

...
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\0消息覆盖)。例如:

(gdb) printf "%s\n", ((MyBEEntry->st_activity)+22)