</>
Plan du cours — 33/64

Verrous de lignes : FOR UPDATE, SKIP LOCKED

Avancé

Quand plusieurs transactions décident à partir de la même ligne, on la verrouille pour sérialiser l'accès et éviter les mises à jour perdues.

BEGIN;
SELECT stock FROM produits WHERE id = 42 FOR UPDATE;    -- verrou exclusif sur la ligne
UPDATE produits SET stock = stock - 1 WHERE id = 42;
COMMIT;

Mieux : laisser la base faire l'opération atomiquement#

-- Une seule instruction atomique : pas de verrou explicite nécessaire
UPDATE produits
SET    stock = stock - 1
WHERE  id = 42 AND stock > 0
RETURNING stock;             -- 0 ligne renvoyée = rupture de stock

Les modes de verrouillage#

ClauseUsage
FOR UPDATEJe vais modifier ou supprimer cette ligne
FOR NO KEY UPDATEJe modifie sans toucher aux clés (moins bloquant pour les clés étrangères)
FOR SHAREJe lis et je veux empêcher toute modification
NOWAITÉchoue immédiatement plutôt que d'attendre le verrou
SKIP LOCKEDIgnore les lignes déjà verrouillées par d'autres

File de tâches avec SKIP LOCKED#

-- Chaque worker prend une tâche non encore traitée, sans bloquer les autres
UPDATE taches
SET    statut = 'en_cours', demarre_le = now()
WHERE  id = (
    SELECT id FROM taches
    WHERE  statut = 'a_faire'
    ORDER  BY cree_le
    LIMIT  1
    FOR UPDATE SKIP LOCKED
)
RETURNING *;

Cas pratique : FOR UPDATE SKIP LOCKED transforme une table PostgreSQL en file de tâches fiable pour des volumes modérés (jusqu'à quelques milliers de tâches par seconde) : pas de double traitement, pas d'attente entre workers, et l'atomicité de la base.