Comment corriger UNABLE_TO_LOCK_ROW dans les déploiements Salesforce

Un enregistrement que le déploiement doit mettre à jour est verrouillé par une autre transaction s'exécutant simultanément.

Apparaît pendant : le DML à l'exécution, une collision de timing plutôt qu'un problème de métadonnées ou de données

Ce que cela signifie

UNABLE_TO_LOCK_ROW signifie que Salesforce n'a pas pu acquérir de verrou sur un enregistrement parce qu'une autre transaction, un job batch, un flow planifié, ou un test Apex concurrent, était déjà en train de le mettre à jour. C'est un problème de timing, pas de métadonnées : le déploiement ou ses tests sont corrects, mais ils sont entrés en collision avec autre chose s'exécutant dans l'org.

C'est particulièrement fréquent avec les relations maîtres-détails, car la mise à jour de tout enregistrement enfant acquiert un verrou sur le parent pour le recalcul du roll-up summary, donc deux insertions d'enfants tentant de mettre à jour le même parent en même temps se disputeront ce verrou.

Diagnostic

Causes courantes

Déploiement pendant une utilisation active de l'org
Un autre utilisateur ou processus planifié met à jour les mêmes enregistrements parents pendant l'exécution des tests Apex du déploiement.
Des tests mettent à jour un enregistrement singleton partagé
Plusieurs classes de test mettent à jour en parallèle le même enregistrement de configuration ou de paramètres à l'échelle de l'org.
Les roll-ups maître-détail se disputent le parent
Plusieurs insertions d'enfants déclenchent simultanément des recalculs de roll-up summary sur le même enregistrement maître.

La solution

  1. Réessayez le déploiement
    Les verrous de ligne sont temporaires. Relancer le même déploiement réussit souvent une fois la transaction concurrente terminée.
  2. Déployez pendant une fenêtre de faible activité
    Planifiez les déploiements en production en dehors des heures ouvrées ou mettez d'abord en pause les jobs planifiés conflictuels.
  3. Évitez la contention sur un enregistrement partagé dans les tests
    Restructurez les tests Apex afin qu'ils ne mettent pas tous à jour le même enregistrement de paramètres singleton au sein de la même transaction.
    for (Account parent : [SELECT Id FROM Account WHERE Id IN :parentIds FOR UPDATE]) {
        // lock parents explicitly and predictably before child DML
    }
En pratique

Comment Serpent évite cela

Serpent AI planifie les déploiements pour éviter les jobs conflictuels connus, et une ligne verrouillée se traduit par une nouvelle tentative en un clic sur la même tâche au lieu d'une release en échec. Consultez la bibliothèque des erreurs de déploiement Salesforce.

Tableau de bord des releases avec alertes de conflit dans Serpent

Prévention

Donnez aux jobs en masse et aux flows planifiés des fenêtres non chevauchantes
Échelonnez les jobs batch planifiés, les chargements de données et les déploiements afin qu'ils ne se disputent pas les mêmes enregistrements parents en même temps.
Concevez les enregistrements de paramètres singleton partagés pour une faible contention
Évitez que de nombreuses classes de test ou déclencheurs indépendants écrivent tous dans un seul enregistrement de paramètres à l'échelle de l'org ; divisez la configuration par domaine lorsque c'est possible.
Intégrez une nouvelle tentative automatique dans l'outillage de déploiement pour cette erreur spécifique
Configurez la CI pour détecter spécifiquement UNABLE_TO_LOCK_ROW et réessayer automatiquement une ou deux fois, car c'est l'une des rares erreurs Salesforce où une simple nouvelle tentative est la bonne solution.
Questions fréquentes

UNABLE_TO_LOCK_ROW, expliqué

UNABLE_TO_LOCK_ROW est-il jamais causé par de mauvaises métadonnées ?
Rarement. C'est presque toujours une collision de timing avec un autre processus, c'est pourquoi le simple fait de relancer le déploiement résout la plupart des cas.
L'utilisation de FOR UPDATE en SOQL évite-t-elle cette erreur ou la provoque-t-elle ?
FOR UPDATE acquiert délibérément un verrou, il peut donc déclencher UNABLE_TO_LOCK_ROW si une autre transaction détient déjà le verrou ; utilisé correctement, il rend le verrouillage explicite et prévisible plutôt qu'accidentel.
Combien de fois un pipeline doit-il réessayer avant de traiter cela comme un véritable échec ?
Deux ou trois nouvelles tentatives avec un court délai entre elles capturent la grande majorité des collisions de verrou transitoires ; si l'échec persiste après cela, traitez-le comme un véritable problème de conception à investiguer.

Commencez gratuitement. Sans carte bancaire, sans installation, sans engagement.

Configuration en moins de 15 minutes. Aucune embauche DevOps nécessaire.

Curieux de livrer plus vite avant de vous lancer ? Parlons-en

Sans engagement.