Verrouillage optimiste vs pessimiste

572

Je comprends les différences entre le verrouillage optimiste et pessimiste. Maintenant, quelqu'un pourrait-il m'expliquer quand j'utiliserais l'un ou l'autre en général?

Et la réponse à cette question change-t-elle selon que j'utilise ou non une procédure stockée pour effectuer la requête?

Mais juste pour vérifier, optimiste signifie "ne verrouille pas la table pendant la lecture" et pessimiste signifie "verrouille la table pendant la lecture".

Jason Baker
la source
1
blog.couchbase.com/…
Frank Myat jeu
1
C'est une bonne question en particulier parce que dans la sérialisation, je lis At any technique type conflicts should be detected and considered, with similar overhead for both materialized and non-materialized conflicts.
Little Alien
1
Ici vous pouvez trouver une bonne explication, ici sur SO, sur le concept racine du verrouillage optimiste .
Diego Mazzaro

Réponses:

812

Le verrouillage optimiste est une stratégie où vous lisez un enregistrement, notez un numéro de version (d'autres méthodes pour ce faire impliquent des dates, des horodatages ou des sommes de contrôle / hachages) et vérifiez que la version n'a pas changé avant de réécrire l'enregistrement. Lorsque vous réécrivez l'enregistrement, vous filtrez la mise à jour sur la version pour vous assurer qu'elle est atomique. (c.-à-d. n'a pas été mis à jour entre le moment où vous vérifiez la version et l'écriture de l'enregistrement sur le disque) et mettez à jour la version en une seule fois.

Si l'enregistrement est sale (c'est-à-dire une version différente de la vôtre), vous abandonnez la transaction et l'utilisateur peut la redémarrer.

Cette stratégie est plus applicable aux systèmes à volume élevé et aux architectures à trois niveaux où vous ne maintenez pas nécessairement une connexion à la base de données pour votre session. Dans cette situation, le client ne peut pas réellement maintenir les verrous de base de données car les connexions sont prises à partir d'un pool et vous n'utilisez peut-être pas la même connexion d'un accès à l'autre.

Le verrouillage pessimiste consiste à verrouiller l'enregistrement pour votre usage exclusif jusqu'à ce que vous en ayez terminé. Il a une bien meilleure intégrité que le verrouillage optimiste mais vous oblige à être prudent avec la conception de votre application pour éviter les blocages . Pour utiliser le verrouillage pessimiste, vous avez besoin d'une connexion directe à la base de données (comme ce serait généralement le cas dans une application serveur client à deux niveaux ) ou d'un ID de transaction disponible en externe qui peut être utilisé indépendamment de la connexion.

Dans ce dernier cas, vous ouvrez la transaction avec le TxID, puis vous reconnectez à l'aide de cet ID. Le SGBD maintient les verrous et vous permet de récupérer la session via le TxID. C'est ainsi que fonctionnent les transactions distribuées utilisant des protocoles de validation en deux phases (telles que les transactions XA ou COM + ).

ConcernedOfTunbridgeWells
la source
148
Le verrouillage optimiste n'utilise pas nécessairement un numéro de version. D'autres stratégies incluent l'utilisation (a) d'un horodatage ou (b) de l'état entier de la ligne elle-même. Cette dernière stratégie est moche mais évite le besoin d'une colonne de version dédiée, dans les cas où vous ne pouvez pas modifier le schéma.
Andrew Swan,
2
@geek - Les protocoles de transaction distribués tels que XA permettent de réticuler un identifiant de transaction distinct autour d'un ou plusieurs systèmes. Ce type de protocole permet aux verrous d'être utilisés via des connexions regroupées car l'identifiant de transaction est découplé des sessions et fourni explicitement. Cependant, cela entraîne des frais généraux et est sujet à des verrous de fuite et à des identifiants de transaction si votre application ne scrute pas scrupuleusement leur suivi. C'est une solution beaucoup plus lourde.
ConcernedOfTunbridgeWells
22
@supercat - Je ne suis pas d'accord pour dire que le verrouillage optimiste est précis à moins de 100% - tant qu'il vérifie tous les enregistrements d'entrée pour une transaction qui ne devrait pas être modifiée pendant la durée, il est aussi précis que le verrouillage pessimiste (sélectionnez le style de mise à jour) sur ceux mêmes enregistrements. La principale différence est que le verrouillage optimiste n'entraîne des frais généraux qu'en cas de conflit, tandis que le verrouillage pessimiste a réduit les frais généraux en cas de conflit. L'optimisme est donc préférable dans le cas où la plupart des transactions n'entrent pas en conflit - ce qui, j'espère, est généralement le cas pour la plupart des applications.
RichVel
2
@Legends - L'utilisation du verrouillage optimsitic serait certainement une stratégie appropriée pour une application Web.
ConcernedOfTunbridgeWells
2
Vous devez mentionner que le choix dépend également du rapport lecture / écriture: si votre application est principalement une application en lecture seule par beaucoup d'utilisateurs, et parfois vous écrivez des données, optez pour un verrouillage optimiste. StackOverflow, par exemple, a beaucoup de gens qui lisent des pages, et parfois quelqu'un en édite une: en verrouillage pessimiste, qui obtiendrait le verrou? le premier? Dans un verrouillage optimiste, la personne qui souhaite éditer la page peut le faire tant qu'elle en a la dernière version.
jehon
177

Le verrouillage optimiste est utilisé lorsque vous ne vous attendez pas à de nombreuses collisions. Faire une opération normale coûte moins cher, mais si la collision se produit, vous devrez payer un prix plus élevé pour la résoudre car la transaction est abandonnée.

Le verrouillage pessimiste est utilisé lorsqu'une collision est anticipée. Les transactions qui violeraient la synchronisation sont simplement bloquées.

Pour sélectionner le mécanisme de verrouillage approprié, vous devez estimer le nombre de lectures et d'écritures et planifier en conséquence.

Ilya Kochetov
la source
Dans le cas normal, la déclaration est parfaite mais dans des cas spéciaux où vous pourriez gérer l' opération CAS permettant une inexactitude comme @skaffman mentionné dans la réponse, je dirais que cela dépend vraiment.
Entendu
75

Optimiste suppose que rien ne changera pendant que vous le lisez.

Pessimiste suppose que quelque chose va le verrouiller.

S'il n'est pas essentiel que les données soient parfaitement lues, utilisez l'optimisme. Vous pourriez obtenir la lecture «sale» étrange - mais il est beaucoup moins susceptible d'entraîner des blocages et autres.

La plupart des applications Web fonctionnent bien avec des lectures sales - en de rares occasions, les données ne correspondent pas exactement à la prochaine recharge.

Pour les opérations de données exactes (comme dans de nombreuses transactions financières), utilisez pessimiste. Il est essentiel que les données soient lues avec précision, sans modifications non affichées - la surcharge de verrouillage supplémentaire en vaut la peine.

Oh, et Microsoft SQL Server utilise par défaut le verrouillage de page - essentiellement la ligne que vous lisez et quelques-uns de chaque côté. Le verrouillage des lignes est plus précis mais beaucoup plus lent. Il vaut souvent la peine de définir vos transactions en lecture validée ou sans verrouillage pour éviter les blocages lors de la lecture.

Keith
la source
Le verrouillage optimiste JPA vous permet de garantir la cohérence de la lecture.
Gili
4
La cohérence en lecture est une préoccupation distincte - avec PostgreSQL, Oracle et de nombreuses autres bases de données, vous obtenez une vue cohérente des données quelles que soient les mises à jour non encore validées, et vous n'êtes pas affecté même par les verrous de ligne exclusifs.
RichVel
Je dois être d'accord avec @RichVel. D'une part, je peux voir comment un verrouillage pessimiste pourrait empêcher des lectures sales si votre niveau d'isolement de transaction est LECTURE NON ENGAGÉE. Mais il est trompeur de dire que le verrouillage optimiste est susceptible de lectures sales sans mentionner que la plupart des bases de données (y compris apparemment MS SQL Server) ont un niveau d'isolement par défaut "READ COMMITTED", ce qui empêche les lectures sales et rend le verrouillage optimiste aussi précis que pessimiste.
antinome
Eric Brower dit que les banquiers, contrairement aux autres, préfèrent les opérations sales. Vos gourous semblent absolument sortis des chariots.
Little Alien
1
Eric Brewer est le gourou qui a donné le théorème de la PAC sur la cohérence des opérations bancaires . C'est contraire à ce que vous lui faites honneur.
Little Alien
50

En plus de ce qui a déjà été dit:

  • Il faut dire que le optimisticverrouillage tend à améliorer la concurrence au détriment de la prévisibilité.
  • Pessimisticle verrouillage tend à réduire la simultanéité, mais est plus prévisible. Vous payez votre argent, etc ...
skaffman
la source
3
Je ne vois pas comment la prévisibilité (quelle que soit votre définition) est améliorée avec un verrouillage pessimiste - si vous voulez dire que `` la transaction peut se terminer une fois les verrous pris '', vous avez raison, mais jusqu'à ce que la transaction ait tous les verrous requis, il pourrait y avoir un délai pour obtenir les verrous restants, et peuvent en fait être abandonnés en raison de la logique de détection + résolution du blocage de la base de données. Les applications utilisant un verrouillage pessimiste peuvent avoir des temps d'exécution très imprévisibles - l'exemple classique est que quelqu'un verrouille un enregistrement X puis va déjeuner, puis un utilisateur verrouille l'enregistrement X et Y, puis un autre Y et Z, et ainsi de suite jusqu'à ce que la plupart des utilisateurs soient bloqués. ..
RichVel
40

Lorsque vous traitez des conflits, vous avez deux options:

  • Vous pouvez essayer d'éviter le conflit, et c'est ce que fait le verrouillage pessimiste.
  • Ou, vous pouvez permettre au conflit de se produire, mais vous devez le détecter lors de la validation de vos transactions, et c'est ce que fait le verrouillage optimiste.

Maintenant, considérons l' anomalie de mise à jour perdue suivante :

Mise à jour perdue

L'anomalie de mise à jour perdue peut se produire au niveau d'isolement de lecture validée.

Dans le diagramme ci-dessus, nous pouvons voir qu'Alice croit qu'elle peut lui retirer 40 accountmais ne se rend pas compte que Bob vient de modifier le solde du compte, et maintenant il ne reste que 20 dans ce compte.

Verrouillage pessimiste

Le verrouillage pessimiste atteint cet objectif en prenant un verrou partagé ou en lecture sur le compte afin que Bob ne puisse pas modifier le compte.

Verrouillage pessimiste de la mise à jour perdue

Dans le diagramme ci-dessus, Alice et Bob acquerront un verrou de lecture sur la accountligne du tableau que les deux utilisateurs ont lu. La base de données acquiert ces verrous sur SQL Server lors de l'utilisation de la lecture répétable ou de la sérialisation.

Étant donné qu'Alice et Bob ont lu le accountavec la valeur PK de 1, aucun d'eux ne peut le modifier jusqu'à ce qu'un utilisateur relâche le verrou de lecture. En effet, une opération d'écriture nécessite une acquisition de verrouillage en écriture / exclusif et les verrous partagés / en lecture empêchent les verrous en écriture / exclusifs.

Ce n'est qu'après qu'Alice a validé sa transaction et que le verrou de lecture a été libéré sur la accountligne, Bob UPDATEreprendra et appliquera la modification. Jusqu'à ce qu'Alice libère le verrou de lecture, les mises à jour de Bob se bloquent.

Pour plus de détails sur la façon dont les infrastructures d'accès aux données utilisent la prise en charge du verrouillage pessimiste de la base de données sous-jacente, consultez cet article .

Verrouillage optimiste

Le verrouillage optimiste permet au conflit de se produire mais le détecte lors de l'application de la MISE À JOUR d'Alice car la version a changé.

Transactions au niveau de l'application

Cette fois, nous avons une versioncolonne supplémentaire . La versioncolonne est incrémentée chaque fois qu'un UPDATE ou DELETE est exécuté, et elle est également utilisée dans la clause WHERE des instructions UPDATE et DELETE. Pour que cela fonctionne, nous devons émettre SELECT et lire le courant versionavant d'exécuter UPDATE ou DELETE, car sinon, nous ne saurions pas quelle valeur de version passer à la clause WHERE ou incrémenter.

Pour plus de détails sur la façon dont les infrastructures d'accès aux données implémentent un verrouillage optimiste, consultez cet article .

Transactions au niveau de l'application

Des systèmes de bases de données relationnelles sont apparus à la fin des années 70 et au début des années 80, lorsqu'un client se connectait généralement à un ordinateur central via un terminal. C'est pourquoi nous voyons toujours des systèmes de base de données définir des termes tels que le paramètre SESSION.

De nos jours, sur Internet, nous n'exécutons plus les lectures et les écritures dans le contexte de la même transaction de base de données, et ACID n'est plus suffisant.

Par exemple, considérez le cas d'utilisation suivant:

entrez la description de l'image ici

Sans verrouillage optimiste, il est impossible que cette mise à jour perdue soit interceptée même si les transactions de la base de données utilisaient Serializable. En effet, les lectures et les écritures sont exécutées dans des requêtes HTTP distinctes, donc sur différentes transactions de base de données.

Ainsi, un verrouillage optimiste peut vous aider à éviter les mises à jour perdues même lorsque vous utilisez des transactions au niveau de l'application qui intègrent également le temps de réflexion de l'utilisateur.

Pour plus de détails sur les transactions logiques ou au niveau de l'application, consultez cet article .

Conclusion

Le verrouillage optimiste est une technique très utile, et il fonctionne très bien même lorsque vous utilisez des niveaux d'isolement moins stricts, comme Read Committed, ou lorsque des lectures et des écritures sont exécutées dans des transactions de base de données ultérieures.

L'inconvénient d'un verrouillage optimiste est qu'un retour en arrière sera déclenché par le cadre d'accès aux données lors de la capture d'un OptimisticLockException, perdant ainsi tout le travail que nous avons effectué précédemment par la transaction en cours d'exécution.

Plus il y a de conflits, plus il y a de conflits et plus les chances d'abandonner des transactions sont grandes. Les annulations peuvent être coûteuses pour le système de base de données car il doit annuler toutes les modifications en cours qui peuvent impliquer à la fois des lignes de table et des enregistrements d'index.

Pour cette raison, le verrouillage pessimiste peut être plus approprié lorsque des conflits surviennent fréquemment, car il réduit les chances de faire reculer les transactions.

Vlad Mihalcea
la source
Pour quels scénarios suggéreriez-vous de choisir OptimisticLocking et PessimisticLocking? Cela dépend-il de la fréquence à laquelle une exception OptimisticLockException se produit?
Stimpson Cat
1
Cela dépend du cas d'utilisation. Parfois, le verrouillage optimiste est la seule solution (par exemple, les transactions multi-requêtes). D'autres fois, le verrouillage pessimiste est la seule solution (par exemple, les verrous consultatifs PostgreSQL ). Parfois, vous devez les combiner, comme c'est le cas avec PESSIMISTIC_FORCE_INCREMENT.
Vlad Mihalcea
22

Je penserais à un autre cas où le verrouillage pessimiste serait un meilleur choix.

Pour un verrouillage optimiste, chaque participant à la modification des données doit accepter d'utiliser ce type de verrouillage. Mais si quelqu'un modifie les données sans se soucier de la colonne de version, cela gâchera toute l'idée du verrouillage optimiste.

Nikolay
la source
Les personnes qui tentent d'utiliser un verrouillage optimiste et pessimiste peuvent également marcher les uns sur les autres, pour ainsi dire. Imaginez un scénario dans lequel une session optimiste lit un enregistrement et effectue des calculs pendant qu'une session pessimiste met à jour l'enregistrement, puis la session optimiste revient et met à jour ce même enregistrement sans noter les modifications apportées. Sélectionnez ... pour la mise à jour ne fonctionne que si chaque session utilise la même syntaxe.
lusional
Bonne explication, Donnez-moi votre vote
Dulaj Kulathunga
15

Il existe essentiellement deux réponses les plus populaires. Le premier dit essentiellement

Optimistic a besoin d'une architecture à trois niveaux où vous ne maintenez pas nécessairement une connexion à la base de données pour votre session, tandis que le verrouillage pessimiste consiste à verrouiller l'enregistrement pour votre usage exclusif jusqu'à ce que vous en ayez terminé. Il a une bien meilleure intégrité qu'un verrouillage optimiste, vous avez besoin d'une connexion directe à la base de données.

Une autre réponse est

optimiste (versionnage) est plus rapide en raison de l'absence de verrouillage mais le verrouillage (pessimiste) fonctionne mieux lorsque le conflit est élevé et il est préférable d'empêcher le travail plutôt que de le rejeter et de recommencer.

ou

Le verrouillage optimiste fonctionne mieux lorsque vous avez de rares collisions

Comme il est mis sur cette page.

J'ai créé ma réponse pour expliquer comment «garder la connexion» est lié aux «faibles collisions».

Pour comprendre quelle stratégie vous convient le mieux, ne pensez pas aux transactions par seconde de votre base de données, mais à la durée d'une seule transaction. Normalement, vous ouvrez la transaction, effectuez une opération et fermez la transaction. Il s'agit d'une transaction courte et classique qu'ANSI avait en tête et très bien pour éviter le verrouillage. Mais comment mettre en place un système de réservation de billets où de nombreux clients réservent les mêmes chambres / sièges en même temps?

Vous parcourez les offres, remplissez le formulaire avec de nombreuses options disponibles et les prix actuels. Cela prend beaucoup de temps et les options peuvent devenir obsolètes, tous les prix invalides entre vous ont commencé à remplir le formulaire et appuyez sur le bouton "J'accepte" car il n'y avait pas de verrouillage sur les données auxquelles vous avez accédé et quelqu'un d'autre, plus agile, a interféré changer tous les prix et vous devez recommencer avec de nouveaux prix.

À la place, vous pouvez verrouiller toutes les options lorsque vous les lisez. Il s'agit d'un scénario pessimiste. Vous voyez pourquoi ça craint. Votre système peut être détruit par un seul clown qui commence simplement une réservation et va fumer. Personne ne peut rien réserver avant d'avoir terminé. Votre flux de trésorerie tombe à zéro. C'est pourquoi, des réserves optimistes sont utilisées dans la réalité. Ceux qui traînent trop longtemps doivent recommencer leur réservation à des prix plus élevés.

Dans cette approche optimiste, vous devez enregistrer toutes les données que vous lisez (comme dans la mienne Lecture répétée ) et arriver au point de validation avec votre version des données (je veux acheter des actions au prix que vous avez affiché dans ce devis, pas au prix actuel ). À ce stade, une transaction ANSI est créée, qui verrouille la base de données, vérifie si rien n'est modifié et valide / abandonne votre opération. IMO, c'est une émulation efficace de MVCC , qui est également associée à Optimistic CC et suppose également que votre transaction redémarre en cas d'abandon, c'est-à-dire que vous ferez une nouvelle réservation. Une transaction implique ici des décisions d'un utilisateur humain.

Je suis loin de comprendre comment implémenter le MVCC manuellement mais je pense que les transactions de longue durée avec option de redémarrage sont la clé pour comprendre le sujet. Corrigez-moi si je me trompe quelque part. Ma réponse a été motivée par ce chapitre d'Alex Kuznecov .

Little Alien
la source
12

Dans la plupart des cas, un verrouillage optimiste est plus efficace et offre des performances supérieures. Lors du choix entre un verrouillage pessimiste et optimiste, tenez compte des éléments suivants:

  • Le verrouillage pessimiste est utile s'il y a beaucoup de mises à jour et des chances relativement élevées pour les utilisateurs d'essayer de mettre à jour les données en même temps. Par exemple, si chaque opération peut mettre à jour un grand nombre d'enregistrements à la fois (la banque peut ajouter des intérêts créditeurs à chaque compte à la fin de chaque mois) et que deux applications exécutent ces opérations en même temps, elles auront des conflits .

  • Le verrouillage pessimiste est également plus approprié dans les applications contenant de petites tables fréquemment mises à jour. Dans le cas de ces soi-disant hotspots, les conflits sont si probables qu'un verrouillage optimiste gaspille des efforts pour annuler les transactions conflictuelles.

  • Le verrouillage optimiste est utile si la possibilité de conflits est très faible - il existe de nombreux enregistrements mais relativement peu d'utilisateurs, ou très peu de mises à jour et principalement des opérations de type lecture.

Koenigsegg
la source
3

Un cas d'utilisation pour un verrouillage optimiste est que votre application utilise la base de données pour permettre à l'un de vos threads / hôtes de «réclamer» une tâche. C'est une technique qui m'a été utile régulièrement.

Le meilleur exemple auquel je peux penser est celui d'une file d'attente de tâches implémentée à l'aide d'une base de données, avec plusieurs threads réclamant des tâches simultanément. Si une tâche a le statut 'Disponible', 'Réclamé', 'Terminé', une requête db peut dire quelque chose comme "Définir le statut = 'Réclamé' où status = 'Disponible'. Si plusieurs threads tentent de modifier le statut de cette manière, tout sauf le premier thread échouera à cause de données sales.

Notez qu'il s'agit d'un cas d'utilisation impliquant uniquement un verrouillage optimiste. Ainsi, au lieu de dire "Un verrouillage optimiste est utilisé lorsque vous ne vous attendez pas à de nombreuses collisions", il peut également être utilisé là où vous vous attendez à des collisions mais souhaitez qu'une seule transaction réussisse.

Charlie Camp
la source
3

Beaucoup de bonnes choses ont été dites ci-dessus à propos du verrouillage optimiste et pessimiste. Un point important à considérer est le suivant:

Lorsque vous utilisez un verrouillage optimiste, nous devons faire attention au fait que l'application se rétablira de ces échecs.

Surtout dans les architectures asynchrones basées sur les messages, cela peut entraîner un traitement des messages en panne ou des mises à jour perdues.

Les scénarios d'échec doivent être réfléchis.

Abhishek Shinde
la source