我正在为我的一个应用程序使用 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_port
(59034
)。
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)