第一部分是正确识别在某个时间点运行的所有查询。为此我使用了这个查询:
SELECT (SELECT COUNT(1) FROM pg_stat_activity) AS total_connections,
(SELECT COUNT(1) FROM pg_stat_activity
WHERE current_query in ('<IDLE>', '<IDLE> in transaction'))
AS idle_connections,
current_query
FROM pg_stat_activity
WHERE current_query NOT IN ('<IDLE>', '<IDLE> in transaction')
AND NOT procpid=pg_backend_pid();
注意! "current_query" 在 postgresql 的更高版本(从 9.2 开始)中简称为 "query"
这会去除所有空闲的数据库连接(查看 IDLE 连接并不能帮助您修复它)并且“NOT procpid=pg_backend_pid()”位会排除此查询本身出现在结果中(这会使您的输出膨胀相当)。如果要隔离特定数据库,还可以按 datname 进行过滤。
我需要以一种非常容易查询的方式获取这些结果,因此我在数据库中使用了一个表。这应该有效:
创建表 connection_audit
(
没有时区的快照时间戳 NOT NULL DEFAULT now(),
total_connections 整数,
idle_connections 整数,
查询文本
)
和 (
OIDS=假
);
这会将当前时间戳、总连接数和空闲连接数以及查询本身存储在“快照”中。
我编写了一个脚本将顶部查询插入到表中,并将其保存到名为“pg_connections.sql”的文件中。
我运行一个脚本每秒将这些结果插入到表格中:
while true ; do psql -U user -d database_name -f 'pg_connections.sql' >> connections.log ; sleep 1; done
这实际上是将所有当前正在执行的查询写入表。
跟踪connections.log 文件向我展示了脚本是否按预期运行(但实际上并不是必需的)。显然,每秒运行这样的脚本可能会对系统造成负担,但是当您没有任何其他方法可以找到此信息时,这是一种短期措施,因此应该值得。只要您需要积累足够的数据,就可以运行此脚本,并希望它会付出代价。