设置:多个网络服务器,运行 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';
当然,大多数结果只是 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 是“真实的”,它就有了锁。由于所有这些结果都已获得批准,pg_locks 是否向我展示了它拥有的锁而不是它正在等待的锁?
现在我正在通过重新启动 Apache 来“修复”这个问题,这似乎使事务变得松散,但显然这不是真正的解决方案。我正在寻找 Postgres 给我一个地方来解决这个问题,特别是因为 Django 应该自动管理它的连接和事务。
最佳答案
特别是对于 Django,此条目详细说明了您看到此问题的原因:
我在这里说“具体”是因为真正的问题是 web 框架/驱动程序/ORM 一直在基于事务的模式下工作(有时在每个奇怪的 SELECT 查询之后调用回滚),而它们实际上应该在一个自动提交模式,仅按需处理交易需求。 Apache::Sessions PostgreSQL 持久化模块是一场灾难(至少在几年前),因为它只在被垃圾收集时才关闭事务。哎呀!
关于PostgreSQL Idle In 事务诊断和读取pg_locks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3312929/