我正在为我的一个应用程序使用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_port
(59034
)可以找到Web服务器上的客户端进程。
sudo netstat -apl | grep 59034
tcp 0 0 ip-10-112-61-218.:59034 db-server:postgresql ESTABLISHED 23843/pgbouncer
我知道我的应用程序代码(我杀了一个运行的应用程序cron并释放了锁)导致连接挂起,但是我无法跟踪它。
这不是很频繁,我找不到任何明确的复制步骤,因为这只发生在生产服务器上。
我想获得有关如何跟踪此类空闲连接的输入,例如:获取最后执行的查询或某种跟踪以确定导致此问题的代码部分。
答案 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)