PostgreSQL空闲事务的诊断和pg_locks读取

16

设置:多个运行mod_wsgi、Apache和连接到运行Postgres 8.3.6的共享数据库的pgbouncer的Web服务器。应用程序正在运行Django。

我们看到的是:在DB上出现了'空闲事务'查询,这些查询会长时间挂起。为了查看它们,我会运行类似以下命令:

SELECT query_start, procpid, client_addr, current_query FROM pg_stat_activity
WHERE query_start < NOW() - interval '5 minutes';

大多数结果当然只是pgbouncer保持打开以供使用的IDLE连接,但有时会出现这些旧的“IDLE in transaction”查询。我理解这意味着有一个查询事务正在等待某些东西,或者有一个BEGIN但尚未达到COMMIT或ROLLBACK的事务。

我的下一步是尝试使用pg_locks确定进程正在等待什么:

select pg_class.relname, pg_locks.transactionid, pg_locks.mode,
       pg_locks.granted as "g", pg_stat_activity.current_query,
       pg_stat_activity.query_start,
       age(now(),pg_stat_activity.query_start) as "age",
       pg_stat_activity.procpid 
from pg_stat_activity,pg_locks
left outer join pg_class on (pg_locks.relation = pg_class.oid)  
where pg_locks.pid=pg_stat_activity.procpid
and pg_stat_activity.procpid = <AN IDLE TRANSACTION PROCESS>
order by query_start;

很多时候,我得到的结果看起来像这样:
 relname | transactionid |      mode       | g |     current_query     |         query_start          |       age       |  client_addr   | procpid 
---------+---------------+-----------------+---+-----------------------+------------------------------+-----------------+----------------+---------
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | ExclusiveLock   | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
         |               | AccessShareLock | t | <IDLE> in transaction | 2010-07-22 15:33:11.48136-04 | 00:23:35.029045 | 192.168.100.99 |    1991
(10 rows)

我不确定如何阅读这个(我猜这源自于我对pg_locks的理解并不是很深)。没有relname,所以它是在等待什么东西吗?我认为如果granted是'true',那么就已经获得了锁。由于所有这些结果都被授予了,那么pg_locks正在显示它拥有的锁而不是正在等待的锁吗?

现在我通过重新启动Apache来“解决”这个问题,这似乎可以使事务开始运转,但显然这不是一个真正的解决方案。我希望Postgres能够告诉我在哪里查找解决方法,特别是因为Django应该自动管理其连接和事务。


2
你看不到relname中的任何内容,很可能的原因是你连接到了错误的数据库。运行查询的连接需要连接到与关系所在的相同的数据库,否则它将无法给出名称。我猜测你在运行查询时连接到了“postgres”数据库或类似的数据库... - Magnus Hagander
1个回答

4
针对 Django,本文详细介绍了为什么会出现这个问题:Threaded Django task...
我在这里说“具体”是因为真正的问题是Web框架/驱动程序/ORM一直在事务模式下工作(有时在每次SELECT查询后调用回滚),而它们应该真正运行在自动提交模式下,并且只在需要时处理事务。Apache::Sessions PostgreSQL持久性模块是一个灾难(至少在几年前是这样),因为它只在垃圾回收时关闭事务。天哪!

据我理解,他发现只有在定时cron作业的上下文中需要手动关闭连接,即Django的连接关闭信号在请求完成时不涉及。这些空闲事务来自未运行任何cron /独立Django进程的Web服务器。 - KRH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接