Errore PostgreSQL: canceling statement due to lock timeout

ERROR:  canceling statement due to lock timeout

Lo statement ha aspettato un lock più a lungo di quanto consente lock_timeout e ha rinunciato. A differenza della maggior parte degli errori in questa lista, questo di solito significa che un meccanismo di sicurezza ha funzionato: fallire in fretta su un lock è quasi sempre meglio che accodarsi dietro di esso — specialmente per il DDL.

Cosa significa questo errore

Perché fallire in fretta conti riguarda la coda, non chi aspetta: un ALTER TABLE ha bisogno di un lock ACCESS EXCLUSIVE. Mentre aspetta dietro qualche query di lunga durata, ogni nuova query su quella tabella — inclusi semplici SELECT — si accoda dietro di esso. Una migrazione bloccata può congelare una tabella di produzione nel giro di secondi. lock_timeout converte quello scenario in un fallimento rapido e riprovabile.

Non confonderlo con statement_timeout: quello limita il tempo di esecuzione totale; lock_timeout limita una singola attesa su un lock e ha il suo SQLSTATE (55P03).

Cause comuni

Come diagnosticarlo

-- Chi blocca chi, adesso:
SELECT waiting.pid, waiting.query AS waiting_query,
       blocking.pid AS blocking_pid, blocking.query AS blocking_query,
       now() - blocking.xact_start AS blocking_xact_age
FROM pg_stat_activity waiting
JOIN pg_stat_activity blocking
  ON blocking.pid = ANY (pg_blocking_pids(waiting.pid));

Imposta anche log_lock_waits = on: le attese più lunghe di deadlock_timeout vengono loggate con entrambi i lati, dandoti una storia della contesa, non solo la vista live.

Come risolverlo

🔍 L'altro modo in cui le attese sui lock finiscono male: deadlock detected.