lunes, 30 de septiembre de 2013

Consulta de Bloqueos en PostgreSql > 9.2 y como matar procesos

Para las versiones de Postgres 9.2 o superiores podéis crear una vista que facilitará la consulta de los procesos que actualmente tiene bloqueos en vuestro sistema:

CREATE OR REPLACE VIEW public.procesos_bloqueantes(
    blocking_pid,
    blocking_user,
    blocking_query,
    blocked_pid,
    blocked_user,
    blocked_query,
    age)
AS
  SELECT kl.pid AS blocking_pid,
         ka.usename AS blocking_user,
         ka.query AS blocking_query,
         bl.pid AS blocked_pid,
         a.usename AS blocked_user,
         a.query AS blocked_query,
         to_char(age(now(), a.query_start), 'HH24h:MIm:SSs' ::text) AS age
  FROM pg_locks bl
       JOIN pg_stat_activity a ON bl.pid = a.pid
       JOIN pg_locks kl ON bl.locktype = kl.locktype AND NOT bl.database IS
         DISTINCT
  FROM kl.database AND NOT bl.relation IS DISTINCT
  FROM kl.relation AND NOT bl.page IS DISTINCT
  FROM kl.page AND NOT bl.tuple IS DISTINCT
  FROM kl.tuple AND NOT bl.virtualxid IS DISTINCT
  FROM kl.virtualxid AND NOT bl.transactionid IS DISTINCT
  FROM kl.transactionid AND NOT bl.classid IS DISTINCT
  FROM kl.classid AND NOT bl.objid IS DISTINCT
  FROM kl.objid AND NOT bl.objsubid IS DISTINCT
  FROM kl.objsubid AND bl.pid <> kl.pid
       JOIN pg_stat_activity ka ON kl.pid = ka.pid
  WHERE kl.granted AND
        NOT bl.granted
  ORDER BY a.query_start;

Una vez localizados los procesos que están produciendo el bloqueo y que sentencia están ejecutando, podemos tomar la decisión de eliminarlos si llevan demasiado tiempo en ejecución y no nos importa perder él resultado de la acción que estaban ejecutando. El identificador de proceso a matar es el "blocking_id" de la vista:

select pg_cancel_backend ( blocking_pid );

jueves, 26 de septiembre de 2013

Indices no utilizados en postgresql

 Consultar los índices de tu bbdd que no están siendo utilizados, para ahorrar espacio o replantearte sus campos:
SELECT
    schemaname || '.' || relname AS table,
    indexrelname AS index,
    pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
    idx_scan as index_scans
  FROM pg_stat_user_indexes ui
  JOIN pg_index i ON ui.indexrelid = i.indexrelid
  WHERE NOT indisunique AND idx_scan < 50 AND pg_relation_size(relid) > 5 * 8192
  ORDER BY pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST,
  pg_relation_size(i.indexrelid) DESC;

viernes, 10 de mayo de 2013

Consulta de Bloqueos en PostgresSql

Si tienes problemas de registros bloqueados en la base de datos ejecuta la siguiente sentencia para visualizar que sentencia/s lo están provocando:

SELECT bl.pid AS blocked_pid, a.usename AS blocked_user,

kl.pid AS blocking_pid, ka.usename AS blocking_user, a.query AS blocked_statement

FROM pg_catalog.pg_locks bl

JOIN pg_catalog.pg_stat_activity a

ON bl.pid = a.pid

JOIN pg_catalog.pg_locks kl

JOIN pg_catalog.pg_stat_activity ka

ON kl.pid = ka.pid

ON bl.transactionid = kl.transactionid AND bl.pid != kl.pid

WHERE NOT bl.granted;

lunes, 11 de marzo de 2013

Ocultar botón de submit para evitar pulsaciones repetidas




martes, 19 de febrero de 2013

Error JPA no sigue secuencias de Postgres

Si os encontrais en JPA que vuestros objetos no siguen las secuencias definidas en Postgres, para el objeto en cuestión, y recibes errores del tipo:

[ERROR]: javax.persistence.PersistenceException: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [

@Id
@SequenceGenerator(name="tabla_id_generator", sequenceName="esquema.tabla_id_seq")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="tabla_id_generator")
@Basic(optional=false)
private Integer id;

Hay un truco que funciona, que es añadir "allocationSize=1":

@Id
@SequenceGenerator(name="tabla_id_generator", sequenceName="esquema.tabla_id_seq",allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="tabla_id_generator")
@Basic(optional=false)
private Integer id;

Por si sirve a alguien.

jueves, 7 de febrero de 2013

Backup y Restore selectivo de tablas o campos con Postgres

pg_dump es una herramienta muy buena para hacer backups de bases de datos completas o tablas enteras.

Pero cuando solo quiero extraer unas pocas columnas (id1,c2,c3) de alguna tabla (t1), de una base de datos (bb1), para restaurarlas posteriormente en otra base de datos diferente (bd2) y tabla diferente de la original que solo contiene los campos que hemos seleccionado (t2), lo mejor es utilizar la utilidad \copy de psql.

Primero descargamos el contenido de la tabla t1 de la base de datos origen bd1, en el fichero salida
psql -h host1 -U postgres bd1 -c "\copy t1 (id1,c2,c3) to salida"

Después borro el contenido de la tabla en la base de datos de destino para que no haya problemas de identificadores duplicados:
psql -h host2 -U postgres bd2 -c "delete from t1"

Por último restauro los datos en la tabla de la base de datos de destino bd2 y tabla destino t2:
psql -h host2 -U postgres bd2 -c "\copy t2 (id1,c2,c3) from salida"

¿Para que sirve esto? Pues por ejemplo si tengo una tabla de usuario con los campos:

id, nick, password, preferencias, dato1, dato2, dato3...

Y en una base de datos diferente necesito una tabla que contenga solo un par de campos de usuario para realizar estudios:

id, nick

Puedo automatizar de forma sencilla, una carga nocturna de los datos.