sql - tabla - ¿Cómo liberar posibles bloqueos de fila de Postgres?
postgresql pdf (4)
Ejecuté una declaración de actualización en una tabla grande de PostgreSQL a través de la interfaz phpPgAdmin. Esto agotó el tiempo, ya que duró demasiado tiempo.
Ahora puedo actualizar algunas filas de esa tabla pero no todas. Intentando actualizar algunas filas se colgará.
¿Están las filas bloqueadas? ¿Cómo puedo permitir que estas filas se actualicen?
¿Qué versión de PostgreSQL está ejecutando? Lo siguiente asume 8.1.8 o posterior (también puede aplicarse a versiones anteriores, no lo sé).
Supongo que quiere decir que se agotó el tiempo de espera de phpPgAdmin: el backend de PostgreSQL llevará todo el tiempo necesario para completar una consulta / actualización. En ese caso, es posible que la sesión original aún esté activa y que la consulta ACTUALIZACIÓN aún se esté ejecutando. Sugiero ejecutar la siguiente consulta (tomada del capítulo 24 de la documentación de PostgreSQL ) en la máquina que aloja el proceso del servidor PostgreSQL, para ver si la sesión aún está viva:
ps auxwww|grep ^postgres
Deben aparecer varias filas: 1 para el proceso maestro de postmaster
y 1 para cada proceso de "escritor", "búfer de estadísticas" y "recopilador de estadísticas". Cualquier línea restante es para procesos que sirven conexiones de base de datos. Estas líneas contendrán el nombre de usuario y la base de datos.
Con suerte, a partir de ahí podrá ver si la sesión en la que realizó la ACTUALIZACIÓN original todavía está pendiente. Aunque en teoría podría encontrar información más detallada pg_stat_activity
desde la vista del sistema pg_stat_activity
, por defecto, PostgreSQL no está configurado para llenar los campos más útiles (como current_query
y query_start
). Vea el capítulo 24 para saber cómo habilitar esto en el futuro.
Si ves que la sesión sigue ahí, mátalo. Deberá iniciar sesión como usuario que ejecuta el proceso (generalmente postgres
) o root para hacerlo. Si no ejecuta el servidor usted mismo, haga que su DBA lo haga por usted.
Una cosa más: para actualizar filas en una tabla, PostgreSQL evita el uso de bloqueos. En su lugar, permite que cada transacción de escritura cree una nueva "versión" de la base de datos, que se convierte en la "versión actual" cuando se confirma la transacción, siempre que no entre en conflicto con las actualizaciones realizadas entretanto por otras transacciones. Así que sospecho que el "ahorcamiento" que estás viendo está causado por otra cosa, aunque no estoy seguro. (¿Ha comprobado las cosas obvias, como si la partición del disco que contiene la base de datos está llena?)
Es posible ver las cerraduras.
Aquí hay una vista para que sea un poco más fácil que usar pg_locks directamente:
CREATE OR REPLACE VIEW public.active_locks AS
SELECT t.schemaname,
t.relname,
l.locktype,
l.page,
l.virtualtransaction,
l.pid,
l.mode,
l.granted
FROM pg_locks l
JOIN pg_stat_all_tables t ON l.relation = t.relid
WHERE t.schemaname <> ''pg_toast''::name AND t.schemaname <> ''pg_catalog''::name
ORDER BY t.schemaname, t.relname;
Entonces simplemente selecciona de la vista:
SELECT * FROM active_locks;
Y matalo con:
SELECT pg_cancel_backend(''%pid%'');
Otras soluciones: http://wiki.postgresql.org/wiki/Lock_Monitoring
Nunca he trabajado con PostreSql, pero si es similar a otros, diría que tiene que cancelar la conexión / finalizar la transacción que contiene los bloqueos.
Sencillo:
Obtener los bloqueos activos de pg_locks:
seleccione t.relname, l.locktype, page, virtualtransaction, pid, mode, otorgado desde pg_locks l, pg_stat_all_tables t donde l.relation = t.relid orden por relación asc;
Copie el pid (ej: 14210) del resultado anterior y sustitúyalo en el siguiente comando.
SELECCIONE pg_terminate_backend (''14210'')