简体   繁体   English

使用Python和PostgreSQL跟踪数据库连接问题

[英]Tracking out of database connection issues with Python and PostgreSQL

I periodically get connection issues to PostgreSQL - either "FATAL: remaining connection slots are reserved for non-replication superuser connections" or "QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 30" depending on whether psycopg or Pyramid is raising the exception. 我定期向PostgreSQL发出连接问题 - “FATAL:剩余连接插槽保留用于非复制超级用户连接”或“QueuePool达到大小5溢出限制10,连接超时,超时30”,具体取决于psycopg或Pyramid是否正在提升例外。 Having established that the transaction manager is properly installed, it's frustrating to not know why I am still running out of connections. 确定事务管理器已正确安装后,不知道为什么我仍然没有连接也很令人沮丧。

I know the connection data is in pg_stat_activity but it's a single snapshot. 我知道连接数据在pg_stat_activity中,但它是一个快照。 Is there any way of seeing connections over time so that I can see just what is actually running over a period of time (ideally from before it's an issue up until the time the issue requires an application restart)? 有没有办法随着时间的推移看到连接,以便我可以看到一段时间内实际运行的是什么(理想情况是从问题发生之前直到问题需要重新启动应用程序)?

The first part is in properly identifying all of the queries running at a point in time. 第一部分是正确识别在某个时间点运行的所有查询。 For that I used this query: 为此,我使用了这个查询:

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();

NOTE! 注意! "current_query" is simply called "query" in later versions of postgresql (from 9.2 on) “current_query”在postgresql的更高版本中简称为“query”(从9.2开始)

This strips out all idle database connections (seeing IDLE connections is not going to help you fix it) and the "NOT procpid=pg_backend_pid()" bit excludes this query itself from showing up in the results (which would bloat your output considerably). 这将删除所有空闲数据库连接(看到IDLE连接不会帮助您修复它),并且“NOT procpid = pg_backend_pid()”位将此查询本身排除在结果中显示(这会大大增加您的输出)。 You can also filter by datname if you want to isolate a particular database. 如果要隔离特定数据库,还可以按datname进行筛选。

I needed these results in a way that was really easy to query them and so I used a table on the database. 我以一种非常容易查询它们的方式需要这些结果,所以我在数据库上使用了一个表。 This should work: CREATE TABLE connection_audit ( snapshot timestamp without time zone NOT NULL DEFAULT now(), total_connections integer, idle_connections integer, query text ) WITH ( OIDS=FALSE ); 这应该工作:CREATE TABLE connection_audit(没有时区的快照时间戳NOT NULL DEFAULT now(),total_connections整数,idle_connections整数,查询文本)WITH(OIDS = FALSE);

This will store the current timestamp in "snapshot", the total and idle connections and the query itself. 这将在“快照”,总连接和空闲连接以及查询本身中存储当前时间戳。

I wrote a script to insert the top query into the table and saved that into a file called "pg_connections.sql". 我编写了一个脚本,将顶级查询插入表中并将其保存到名为“pg_connections.sql”的文件中。

I ran a script to insert these results into the table every second: 我运行了一个脚本,每秒将这些结果插入表中:

while true ; do psql -U user -d database_name -f 'pg_connections.sql' >> connections.log ; sleep 1; done

What this is effectively doing is writing all CURRENTLY executing queries to the table. 这有效的做法是将所有当前正在执行的查询写入表中。

Tailing the connections.log file showed me if the script was running as expected (but it isn't really required). 传递connections.log文件告诉我脚本是否按预期运行(但实际上并不需要)。 Obviously, running a script like this every second can be taxing on a system but it's a short-term measure when you don't have any other way of finding this information out so it should be worth it. 显然,每秒运行一个这样的脚本可能会对系统造成负担,但是当你没有任何其他方式来查找这些信息时这是一个短期措施,所以它应该是值得的。 Run this script for as long as you need to accumulate sufficient data and hopefully it should pay dirt. 只要您需要积累足够的数据,并且希望它应该付出代价,运行此脚本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM