Différence entre «lecture engagée» et «lecture répétable»

245

Je pense que les niveaux d'isolement ci-dessus sont si semblables. Quelqu'un pourrait-il décrire avec de beaux exemples quelle est la principale différence?

Fore
la source
3
Vous devez développer la question et ajouter des balises pour le "niveau d'isolement" auquel vous faites référence (Java, etc.). "niveau d'isolement" est un terme quelque peu ambigu, et vous demandez évidemment une réponse pour un environnement spécifique.
jesup

Réponses:

564

La lecture validée est un niveau d'isolement qui garantit que toutes les données lues ont été validées au moment de la lecture. Cela empêche simplement le lecteur de voir toute lecture intermédiaire, non engagée et «sale». Il ne fait aucune promesse que si la transaction réémet la lecture, trouvera les mêmes données, les données sont libres de changer après avoir été lues.

La lecture répétable est un niveau d'isolement plus élevé, qui en plus des garanties du niveau de lecture engagé, garantit également que les données lues ne peuvent pas changer , si la transaction lit à nouveau les mêmes données, elle trouvera les données précédemment lues en place, inchangées et disponible pour lecture.

Le prochain niveau d'isolement, sérialisable, constitue une garantie encore plus forte: en plus de toutes les garanties de lecture répétables, il garantit également qu'aucune nouvelle donnée ne peut être vue par une lecture ultérieure.

Supposons que vous ayez un tableau T avec une colonne C avec une ligne, disons qu'il a la valeur «1». Et considérez que vous avez une tâche simple comme la suivante:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

C'est une tâche simple qui émet deux lectures à partir du tableau T, avec un délai de 1 minute entre elles.

  • sous READ COMMITTED, le second SELECT peut renvoyer toutes les données. Une transaction simultanée peut mettre à jour l'enregistrement, le supprimer, insérer de nouveaux enregistrements. La deuxième sélection verra toujours les nouvelles données.
  • sous REPEATABLE READ, le deuxième SELECT est garanti pour afficher au moins les lignes qui ont été renvoyées par le premier SELECT inchangées . De nouvelles lignes peuvent être ajoutées par une transaction simultanée au cours de cette minute, mais les lignes existantes ne peuvent pas être supprimées ni modifiées.
  • sous SERIALIZABLE lit la deuxième sélection est garantie de voir exactement les mêmes lignes que la première. Aucune ligne ne peut être modifiée, ni supprimée, ni de nouvelles lignes ne peuvent être insérées par une transaction simultanée.

Si vous suivez la logique ci-dessus, vous pouvez rapidement réaliser que les transactions SERIALISABLES, bien qu'elles puissent vous faciliter la vie, bloquent toujours complètement toutes les opérations simultanées possibles, car elles nécessitent que personne ne puisse modifier, supprimer ou insérer une ligne. Le niveau d'isolement des transactions par défaut de l' System.Transactionsétendue .Net est sérialisable, ce qui explique généralement les performances abyssales qui en résultent.

Et enfin, il y a aussi le niveau d'isolement SNAPSHOT. Le niveau d'isolement SNAPSHOT offre les mêmes garanties que sérialisable, mais pas en exigeant qu'aucune transaction simultanée ne puisse modifier les données. Au lieu de cela, il oblige chaque lecteur à voir sa propre version du monde (c'est son propre «instantané»). Cela le rend très facile à programmer ainsi que très évolutif car il ne bloque pas les mises à jour simultanées. Cependant, cet avantage a un prix: une consommation supplémentaire de ressources serveur.

Lectures supplémentaires:

Remus Rusanu
la source
24
Je pense qu'il y a une erreur ci-dessus pour REPEATABLE READ: vous dites que les lignes existantes ne peuvent pas être supprimées ni modifiées, mais je pense qu'elles peuvent être supprimées ou modifiées car la lecture répétable lit simplement un "instantané" et non les données réelles. Dans les documents dev.mysql.com/doc/refman/5.0/en/… : "Toutes les lectures cohérentes au sein de la même transaction lisent l'instantané établi par la première lecture."
Derek Litz
2
@Derek Litz Ai-je raison de dire que les données PEUVENT / PEUVENT être modifiées par un tiers, pendant la transaction, mais les lectures verront toujours les "anciennes" données originales comme si le changement n'avait pas été effectué lieu (l'instantané).
Programster
5
@Cornstalks. Oui, des lectures fantômes peuvent se produire à partir de suppressions (ou d'insertions). Oui, les lectures fantômes peuvent se produire dans un isolement de lecture répétable (à partir des insertions uniquement). Non, les lectures fantômes à partir de suppressions ne peuvent pas se produire dans un isolement de lecture répétable. Essaye-le. Ce que je dis n'est pas contredit par la documentation que vous avez citée.
AndyBrown
4
@Cornstalks NP. Je ne l'ai mentionné que parce que je n'étais pas sûr à 100% moi-même et j'ai dû plonger profondément pour être sûr de qui avait raison! Et je ne voulais pas que les futurs lecteurs soient trompés. En gardant les commentaires, il vaut probablement mieux garder comme suggéré. Je suis sûr que toute autre personne intéressée par ce niveau de détails sera suffisamment particulière pour lire tous les commentaires !!
AndyBrown
12
Merci de ne pas avoir supprimé vos commentaires. La discussion permet de connecter plus de points.
Josh
68

Lecture répétable

L'état de la base de données est conservé dès le début de la transaction. Si vous récupérez une valeur dans session1, puis mettez à jour cette valeur dans session2, la récupérer à nouveau dans session1 renverra les mêmes résultats. Les lectures sont reproductibles.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Lire Engagé

Dans le cadre d'une transaction, vous récupérerez toujours la dernière valeur validée. Si vous récupérez une valeur dans session1, mettez-la à jour dans session2, puis récupérez-la dans session1à nouveau, vous obtiendrez la valeur telle que modifiée dans session2. Il lit la dernière ligne validée.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Logique?

Hazel_arun
la source
J'ai essayé la lecture répétable dans SQL Server 2008 avec "définir la lecture répétable du niveau d'isolement". Création de deux fenêtres de requête SQL. Mais n'a pas fonctionné. Pourquoi?
Aditya Bokade
1
Pourquoi la deuxième session1 lirait-elle toujours Aaron? La transaction de session2 n'est-elle pas terminée et validée? Je connais ce vieux, mais peut-être que quelqu'un peut faire la lumière.
Sonny Childs
9
Je pense que la lecture répétable bloquera la deuxième session jusqu'à ce que la première session soit validée. Donc l'exemple est faux.
Nighon
4
En cas de lecture répétable, lorsque la session 1 lit la ligne, elle place un verrou partagé, qui ne permettrait aucun verrouillage exclusif (à la session 2) pour la mise à jour, par conséquent les données ne peuvent pas être mises à jour.
Taher
Je pense que SQL Server et MySQL se comportent différemment en ce qui concerne la mise à jour des lignes partagées entre deux transactions
user2488286
23

Simplement la réponse selon ma lecture et ma compréhension de ce fil et de la réponse @ remus-rusanu est basée sur ce scénario simple:

Il existe deux processus A et B. Le processus B lit le tableau X Le processus A écrit dans le tableau X Le processus B lit à nouveau le tableau X.

  • ReadUncommitted : le processus B peut lire les données non validées du processus A et il peut voir différentes lignes en fonction de l'écriture de B. Pas de serrure du tout
  • ReadCommitted : le processus B peut lire UNIQUEMENT les données validées du processus A et il peut voir différentes lignes en fonction de l'écriture B COMMITTED. pourrions-nous l'appeler Simple Lock?
  • RepeatableRead : le processus B lira les mêmes données (lignes) quel que soit le processus A. Mais le processus A peut modifier d'autres lignes. Bloc de niveau de lignes
  • Sérialisable : le processus B lira les mêmes lignes qu'auparavant et le processus A ne peut ni lire ni écrire dans le tableau. Bloc au niveau de la table
  • Instantané : chaque processus a sa propre copie et ils y travaillent. Chacun a sa propre vision
Mo Zaatar
la source
15

Vieille question qui a déjà une réponse acceptée, mais j'aime penser à ces deux niveaux d'isolement en termes de la façon dont ils modifient le comportement de verrouillage dans SQL Server. Cela pourrait être utile pour ceux qui déboguent des blocages comme je l'étais.

LIRE ENGAGÉ (par défaut)

Les verrous partagés sont pris dans SELECT, puis libérés à la fin de l'instruction SELECT . C'est ainsi que le système peut garantir qu'il n'y a pas de lectures incorrectes de données non validées. D'autres transactions peuvent toujours modifier les lignes sous-jacentes une fois votre SELECT terminé et avant la fin de votre transaction.

REPEATABLE READ

Les verrous partagés sont pris dans SELECT, puis libérés uniquement une fois la transaction terminée . C'est ainsi que le système peut garantir que les valeurs que vous lisez ne changeront pas pendant la transaction (car elles restent verrouillées jusqu'à la fin de la transaction).

Chris Gillum
la source
13

Essayer d'expliquer ce doute avec des diagrammes simples.

Lire validée: ici, dans ce niveau d'isolement, la transaction T1 lira la valeur mise à jour du X validé par la transaction T2.

Lire Engagé

Lecture répétable: dans ce niveau d'isolement, la transaction T1 ne prendra pas en compte les modifications validées par la transaction T2.

entrez la description de l'image ici

vkrishna17
la source
1

Je pense que cette image peut aussi être utile, elle m'aide comme référence lorsque je veux me souvenir rapidement des différences entre les niveaux d'isolement (merci à kudvenkat sur youtube)

entrez la description de l'image ici

Ivan Pavičić
la source
0

Veuillez noter que la répétition en lecture répétable concerne un tuple, mais pas l'ensemble du tableau. Dans les niveaux d'isolement ANSC, une anomalie de lecture fantôme peut se produire, ce qui signifie que lire une table avec la même clause where peut renvoyer deux fois différents jeux de résultats différents. Littéralement, ce n'est pas répétable .

不辞 长 做 岭南 人
la source
-1

Mon observation sur la solution initiale acceptée.

Sous RR (mysql par défaut) - Si un tx est ouvert et qu'un SELECT a été déclenché, un autre tx ne peut PAS supprimer une ligne appartenant au jeu de résultats READ précédent tant que le tx précédent n'est pas validé (en fait, la suppression de l'instruction dans le nouveau tx se bloquera simplement) , mais le tx suivant peut supprimer toutes les lignes de la table sans aucun problème. Btw, une prochaine LECTURE dans le tx précédent verra toujours les anciennes données jusqu'à ce qu'elles soient validées.

Sanjeev Dhiman
la source
2
Vous voudrez peut-être le mettre dans la section des commentaires pour que le répondeur soit averti. Il pourra ainsi répondre à vos observations et apporter des corrections si besoin.
RBT