learn.chetana.fr

Concurrence : transactions, verrous, SKIP LOCKED

14 min de lectureAvancé

MVCC : pourquoi les lecteurs ne bloquent pas les écrivains

Postgres utilise le MVCC (Multi-Version Concurrency Control) : chaque transaction voit un instantanĂ© cohĂ©rent de la base. Une Ă©criture crĂ©e une nouvelle version de la ligne sans dĂ©truire l'ancienne — les lecteurs continuent de voir leur version. ConsĂ©quence pratique : les lectures ne bloquent jamais les Ă©critures et inversement. Les conflits n'arrivent qu'entre Ă©crivains sur la mĂȘme ligne.

Corollaire opĂ©rationnel : les versions mortes s'accumulent → VACUUM (auto en gĂ©nĂ©ral) les recycle. Une table trĂšs Ă©crite mal vacuumĂ©e « gonfle » (bloat) — un classique de prod Ă  connaĂźtre.

Les niveaux d'isolation (ce qu'ils garantissent)

  • Read Committed (dĂ©faut) : chaque requĂȘte voit ce qui est committĂ© Ă  son dĂ©marrage — suffisant pour 95 % des cas ;
  • Repeatable Read : l'instantanĂ© est figĂ© pour toute la transaction (utile pour un rapport cohĂ©rent multi-requĂȘtes) ;
  • Serializable : comme si les transactions s'exĂ©cutaient en sĂ©rie — la base dĂ©tecte les anomalies et fait Ă©chouer une transaction (Ă  toi de la rejouer). Le prix de la garantie maximale.

La rĂšgle : rester en Read Committed, monter d'un cran seulement quand une anomalie prĂ©cise le justifie — et savoir gĂ©rer le serialization_failure (retry) si tu montes Ă  Serializable.

Les verrous applicatifs et le pattern file d'attente

Le cours Stack IA a montrĂ© FOR UPDATE SKIP LOCKED pour le polling email et le reconciler de jobs — voici le pourquoi :

-- N workers se partagent une file, sans coordinateur externe :
SELECT * FROM jobs WHERE status = 'pending'
ORDER BY created_at
FOR UPDATE SKIP LOCKED       -- verrouille MES lignes, SAUTE celles des autres
LIMIT 10;
-- 
 traiter 
 UPDATE status = 'done' 
 COMMIT (libùre les verrous)
  • FOR UPDATE : verrouille les lignes lues (les autres transactions attendent) ;
  • SKIP LOCKED : au lieu d'attendre, saute les lignes dĂ©jĂ  verrouillĂ©es → chaque worker prend un lot disjoint, zĂ©ro contention. C'est ce qui transforme une table en file d'attente concurrente sans Redis ni RabbitMQ ;
  • NOWAIT : variante qui Ă©choue immĂ©diatement au lieu de sauter (quand tu veux savoir que c'est verrouillĂ©).

Et les advisory locks (pg_advisory_lock) pour un verrou applicatif nommĂ© (« un seul worker exĂ©cute cette tĂąche cron ») — un mutex distribuĂ© gratuit.

đŸ§© Quiz1/3

Grñce au MVCC, en Postgres


🃏 Flashcards1/4