Deadlocks
AvancéUn deadlock survient quand deux transactions s'attendent mutuellement : PostgreSQL le détecte et annule l'une des deux.
-- Transaction A -- Transaction B
BEGIN; BEGIN;
UPDATE comptes SET ... WHERE id = 1; UPDATE comptes SET ... WHERE id = 2;
UPDATE comptes SET ... WHERE id = 2; --> UPDATE comptes SET ... WHERE id = 1; -- chacune attend l'autre
-- ERROR: deadlock detected (40P01)
Les éviter#
- Verrouiller dans un ordre constant : toujours par
idcroissant, par exemple. - Garder les transactions courtes et petites.
- Prendre les verrous nécessaires d'emblée (
SELECT ... FOR UPDATEsur toutes les lignes, triées). - Réessayer la transaction victime : elle échoue avec
40P01.
Diagnostiquer#
SELECT pid, state, wait_event_type, wait_event, now() - xact_start AS duree, left(query, 60)
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY xact_start;
SELECT pg_blocking_pids(12345); -- qui bloque ce processus ?
Activez log_lock_waits = on : les attentes de verrou plus longues que deadlock_timeout (1 s par défaut) sont alors journalisées.