Come terminare una query (o una connessione) in PostgreSQL

Due funzioni, un percorso di escalation: pg_cancel_backend(pid) annulla la query in esecuzione e lascia viva la connessione; pg_terminate_backend(pid) chiude l'intera connessione. Comincia con l'annullamento.

-- 1. Trova il pid (vedi la guida "show running queries" per di più):
SELECT pid, state, now() - query_start AS runtime, left(query, 100)
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY query_start;

-- 2. Annulla la query (gentile — la sessione resta connessa):
SELECT pg_cancel_backend(12345);

-- 3. Se non basta, chiudi la connessione:
SELECT pg_terminate_backend(12345);

Quale, e quando

SituazioneUsa
Una query è lenta / blocca altre, la sessione per il resto è a postopg_cancel_backend
Sessione bloccata in idle in transaction che tiene lock (nulla in esecuzione da annullare)pg_terminate_backend — qui l'annullamento non fa nulla: non c'è alcuna query da annullare, è la transazione aperta che fa danni
Sessione fuori controllo che si riconnette e rilancia la queryTermina, poi sistema il client — ucciderla in loop non è una strategia

Entrambe restituiscono true se il segnale è stato inviato (non è una garanzia che la query sia morta all'istante — l'annullamento viene controllato in punti sicuri, quindi una query bloccata in una chiamata al kernel non interrompibile può metterci un momento). La vittima riceve SQLSTATE 57014 ("canceling statement due to user request") oppure, quando terminata, il suo client vede cadere la connessione.

Pulizia in blocco, fatta con attenzione

-- Termina tutte le sessioni "idle in transaction" da più di 10 minuti:
SELECT pid, pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle in transaction'
  AND xact_start < now() - interval '10 minutes';

Esegui prima la SELECT senza la chiamata a pg_terminate_backend e leggi la lista — poi, e solo allora, aggiungi il kill. Per una soluzione permanente, imposta idle_in_transaction_session_timeout invece di eseguire questo a mano ad ogni incidente.

Cosa non fare mai

Non fare mai kill -9 a un processo backend di PostgreSQL dalla shell. Un backend a cui è stato inviato SIGKILL non può ripulire il suo stato in memoria condivisa, quindi il postmaster deve presumere una corruzione e riavvia l'intero cluster, disconnettendo tutti e rieseguendo il WAL. Quella che sembrava l'uccisione di una singola query diventa un'interruzione totale. Un semplice kill <pid> (SIGTERM) è equivalente a pg_terminate_backend ed è accettabile quando non riesci a ottenere una connessione — ma le funzioni SQL sono sempre preferibili perché non possono colpire il processo sbagliato.

Permessi: puoi sempre annullare/terminare le tue sessioni; per le sessioni di altri utenti ti serve l'appartenenza a pg_signal_backend (o essere superuser).

🔍 Uccidi la stessa query ogni settimana? Visualizza il suo piano con il Visualizzatore EXPLAIN e sistemala una volta per tutte — oppure mettici davanti uno statement_timeout.