设置:多个Web服务器,运行mod_wsgi,Apache和pgbouncer,它们连接到运行Postgres 8.3.6的共享数据库。应用程序正在运行Django。
我们所看到的:'闲置在交易中'查询数据库,这些数据库已经存在了很长时间。为了看到它们,我会运行这样的事情:
SELECT query_start, procpid, client_addr, current_query FROM pg_stat_activity
WHERE query_start < NOW() - interval '5 minutes';
大多数结果当然只是IDL连接,pgbouncer保持开放使用,但有时候会有这些旧的'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,所以它说什么都没有等待?我认为,如果被授予“真实”,它就有了锁定。由于所有这些结果都被授予,pg_locks是否显示了它所拥有的锁而不是它正在等待的锁?
现在我正在通过重启Apache来解决这个问题,这似乎会破坏交易松散,但显然这不是一个真正的解决方案。我正在寻找Postgres给我一个关于在哪里寻找这个问题的地方,特别是因为Django应该自动管理它的连接和交易。
答案 0 :(得分:3)
对于Django,此条目详细说明了您看到此问题的原因:
我在这里说“具体”是因为真正的问题是web框架/驱动程序/ ORM在基于事务的模式下一直工作(有时候在每个freakin'ELEL查询之后调用回滚)它们应该真正运行在自动提交模式,仅在需要的基础上处理交易需求。 Apache :: Sessions PostgreSQL持久性模块是一场灾难(至少在几年前),因为它只在垃圾收集时关闭了事务。糟糕!