Настройка: несколько веб-серверов, работающие с 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';
Большинство результатов, конечно же, - это просто IDLE-соединения, которые pgbouncer поддерживает для использования, но иногда это старые запросы IDLE в транзакции. Я понимаю, что это означает, что есть транзакция запроса, которая ждет чего-то или что-то, что имеет 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). Там нет переименования, так он говорит, что он ничего не ждет? Я думал, что если бы он был "правдой", у него был замок. Поскольку все эти результаты предоставлены, pg_locks показывает мне блокировки, которые у него есть, а не то, что они ждут?
Сейчас я "исправляю" это, перезапуская Apache, который, кажется, трясет транзакции, но, очевидно, это не настоящее решение. Я ищу Postgres, чтобы дать мне место, где искать, чтобы понять это, тем более, что Django должен автоматически управлять своими подключениями и транзакциями.