Настройка: несколько веб-серверов, на которых запущены 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 в транзакции». Я понимаю, что это означает, что существует транзакция запроса, которая ожидает чего-то или чего-то, что имеет НАЧАЛО, но не достигло 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 должен автоматически управлять своими соединениями и транзакциями.