</>
Plan du cours — 63/64

Diagnostiquer un incident en production

Avancé

Quand la base « ne répond plus », on procède dans l'ordre : est-elle saturée, bloquée, ou sans espace ?

1. Connexions saturées#

SELECT state, count(*) FROM pg_stat_activity GROUP BY state;

Beaucoup de active : requêtes lentes ou CPU saturé. Beaucoup d'idle in transaction : l'application garde des transactions ouvertes (fuite, appel externe dans une transaction).

2. Verrous : qui bloque qui ?#

SELECT blocked.pid  AS bloque,
       blocking.pid AS bloquant,
       left(blocked.query, 50)  AS requete_bloquee,
       left(blocking.query, 50) AS requete_bloquante,
       now() - blocking.xact_start AS depuis
FROM   pg_stat_activity blocked
JOIN   LATERAL unnest(pg_blocking_pids(blocked.pid)) AS b(pid) ON true
JOIN   pg_stat_activity blocking ON blocking.pid = b.pid;

Une migration ou une transaction oubliée tient un verrou : pg_cancel_backend(pid) d'abord, pg_terminate_backend(pid) si nécessaire.

3. Disque plein#

  • Causes fréquentes : WAL qui s'accumule (slot de réplication abandonné, archivage en échec), table ou index gonflé, journaux, fichiers temporaires d'un gros tri.
  • Vérifiez les slots : SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) FROM pg_replication_slots;

4. Retard de réplication et lectures obsolètes#

Comparez le retard (pg_stat_replication sur le primaire) et cherchez une transaction longue ou une requête de reporting sur la réplique qui retarde le rejeu.

5. Après l'incident#

  • Post-mortem sans reproche : chronologie, cause racine, ce qui a bien marché, actions (avec responsable et échéance).
  • Transformer chaque détection tardive en alerte ; chaque geste manuel en runbook ou en automatisation.

Astuce : en cas de doute pendant un incident, ne modifiez pas plusieurs choses à la fois : vous ne saurez plus ce qui a corrigé (ou aggravé) la situation. Notez chaque action et son heure.