</>
Plan du cours — 34/64

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#

  1. Verrouiller dans un ordre constant : toujours par id croissant, par exemple.
  2. Garder les transactions courtes et petites.
  3. Prendre les verrous nécessaires d'emblée (SELECT ... FOR UPDATE sur toutes les lignes, triées).
  4. 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.