martes, 16 de febrero de 2010

Postgres Idle in transaction

Durante el desarrollo de una aplicación web, monitoreando el comportamiento de mi persistencia en postgres, me encontré con que tenía varios procesos marcados idle in transaction.

Esto me generó preocupación, porque al tener un pool de conexiones, eventualmente el pool se agotaba, entonces empecé a buscar la razón y me di cuenta que si todo marchara correctamente debería tener varios procesos idle, pero no debería tener procesos idle in transaction.

Empecé a buscar la razón, y me di cuenta que en donde recordaba tener transacciones, el codigo las cerraba correctamente, asi que empecé a buscar la forma de conocer el query que me estaba generando la transaccion incompleta, asi que en la documentación de postgresql encontré [1] que ejecutando el comando ps puedo conocer el pid del proceso que se encuentra en ese estado asi:

~$ ps auxww | grep ^postgres


Parte del resultado de la ejecución de este comando es:


postgres 6795 0.0 0.3 42308 3992 ? Ss 09:50 0:00 postgres: utomcat sendero 127.0.0.1(48818) idle
postgres 6819 0.0 0.4 42304 4308 ? Ss 09:51 0:00 postgres: sendero sendero 127.0.0.1(48824) idle in transaction



De ahi puede saberse que el proceso cuyo pid es 6795 esta sin problemas, pero el proceso 6819 se encuentra con una transaccion inconclusa.

Para saber cuáles son las tablas de la base de datos que tienen los bloqueos, en psql puede ejecutar, como encuentra en [2]:


SELECT relation, pid, mode, granted, relname
FROM pg_locks
INNER JOIN pg_stat_user_tables
ON pg_locks.relation = pg_stat_user_tables.relid
WHERE pg_locks.pid='6819';


En mi caso obtuve:


relation | pid | mode | granted | relname
----------+------+-----------------+---------+-------------------
98377 | 6819 | AccessShareLock | t | t_secciones


Lo que me remitió a un filtro que habia hecho en mi aplicación en el cual no estaba utilizando transacción alguna. PostgreSQL ejecuta todo dentro de una transacción, por ende, al intentar ejecutar código sin crear una transacción, PostgreSQL la creará, sin embargo, si el código no finaliza la transacción, esta quedará inconclusa. Por esto, en mi caso, la solución fue crear una transacción, y realizar el correspondiente commit o rollback en mi código para finalizarla.


[1] http://www.postgresql.org/docs/8.4/interactive/monitoring-ps.html
[2] http://wiki.dspace.org/index.php/Idle_In_Transaction_Problem

No hay comentarios:

Publicar un comentario