Mysql
 sql >> Base de données >  >> RDS >> Mysql

SELECT ... FOR UPDATE doit-il toujours contenir ORDER BY ?

Votre exemple dans votre question montre que l'ordre de verrouillage dépend de la méthode d'accès. Ce chemin d'accès n'est pas directement déterminé par la clause ORDER BY de la requête, de nombreux facteurs peuvent influencer ce chemin d'accès. Par conséquent, vous ne pouvez pas empêcher un blocage en ajoutant simplement un ORDER BY car vous pourriez toujours avoir deux chemins d'accès distincts. En fait, en exécutant votre cas de test avec la commande par et en modifiant les paramètres de session, j'ai pu faire en sorte que deux sessions se déroulent dans un ORA-60 avec la même requête.

Si les sessions concernées n'ont pas d'autre verrou en attente, verrouiller les lignes dans le même ordre dans toutes les sessions empêchera les interblocages, mais comment pouvez-vous forcer cet ordre de manière fiable ? Notez que cela ne ferait que prévenir ce cas très particulier de blocage de toute façon. Vous pourriez toujours avoir des blocages avec plusieurs requêtes dans chaque session ou différents plans.

En pratique, ce cas est vraiment particulier et ne devrait de toute façon pas arriver souvent :si vous vous inquiétez des blocages, je pense toujours qu'il existe des méthodes plus simples pour les éviter.

Le moyen le plus simple d'éviter un blocage consiste à utiliser soit FOR UPDATE NOWAIT ou FOR UPDATE WAIT X (bien que WAIT X puisse toujours déclencher un blocage avec des valeurs de X supérieures au mécanisme de détection de blocage, actuellement 3 secondes à partir de 11g je crois -- merci @APC pour la correction).

En d'autres termes, les deux transactions devraient demander :donnez-moi ces lignes et verrouillez-les, mais si un autre utilisateur a déjà un verrou, renvoyez une erreur au lieu d'attendre indéfiniment. C'est l'attente indéfinie qui provoque les blocages.

En pratique, je dirais que la plupart des applications avec des utilisateurs réels préfèrent recevoir une erreur immédiatement plutôt qu'une transaction attende indéfiniment qu'une autre transaction se termine. Je considérerais FOR UPDATE sans NOWAIT uniquement pour les travaux par lots non critiques.