Relation des niveaux d'isolement des transactions avec les verrous sur la table

105

J'ai lu environ 4 niveaux d'isolement:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

Je veux comprendre le verrou que chaque isolation de transaction prend sur la table

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

Voici les trois phénomènes qui peuvent se produire dans l'isolement des transactions
Lecture sale - pas de verrou
Lecture non répétable - pas de lecture sale comme verrou sur les données validées
Lecture fantôme - verrou sur le bloc de sql (qui est sélectionné à l'aide de la requête de sélection)

Je veux comprendre où nous définissons ces niveaux d'isolement: uniquement au niveau jdbc / hibernate ou dans DB également

PS: J'ai parcouru les liens dans les niveaux d'isolement dans oracle , mais ils ont l'air maladroits et parlent de bases de données spécifiques

Apprenant
la source
3
Cela dépend complètement de la base de données. Différentes bases de données peuvent utiliser différents algorithmes pour les niveaux d'isolement. Certains peuvent utiliser MVCC (pas de verrous sur les requêtes sélectionnées), d'autres utilisent un verrouillage strict en 2 phases (verrous partagés et exclusifs).
thé brb du

Réponses:

157

Je veux comprendre le verrou que chaque isolation de transaction prend sur la table

Par exemple, vous avez 3 processus simultanés A, B et C. A démarre une transaction, écrit des données et valide / annule (selon les résultats). B exécute simplement une SELECTinstruction pour lire les données. C lit et met à jour les données. Tous ces processus fonctionnent sur la même table T.

  • LIRE SANS ENGAGEMENT - pas de verrou sur la table. Vous pouvez lire les données du tableau tout en y écrivant. Cela signifie que A écrit des données (non validées) et B peut lire ces données non validées et les utiliser (dans n'importe quel but). Si A exécute une annulation, B a toujours lu les données et les a utilisées. C'est le moyen le plus rapide mais le moins sûr de travailler avec des données car il peut entraîner des trous de données dans des tables non physiquement liées (oui, deux tables peuvent être liées logiquement mais pas physiquement dans les applications du monde réel = \).
  • LIRE ENGAGÉ - verrouiller les données validées. Vous pouvez lire les données uniquement validées. Cela signifie que A écrit des données et que B ne peut pas lire les données enregistrées par A jusqu'à ce que A exécute une validation. Le problème ici est que C peut mettre à jour les données qui ont été lues et utilisées sur les clients B et B n'auront pas les données mises à jour.
  • REPEATABLE READ - verrouiller sur un bloc de SQL (qui est sélectionné à l'aide d'une requête de sélection). Cela signifie que B lit les données dans certaines conditions, c'est-à WHERE aField > 10 AND aField < 20- dire que A insère des données où la aFieldvaleur est comprise entre 10 et 20, puis B lit à nouveau les données et obtient un résultat différent.
  • SERIALIZABLE - verrouiller sur une table complète (sur laquelle la requête Select est déclenchée). Cela signifie que B lit les données et qu'aucune autre transaction ne peut modifier les données de la table. C'est le moyen le plus sûr mais le plus lent de travailler avec des données. De plus, comme une simple opération de lecture verrouille la table , cela peut conduire à de gros problèmes sur la production: imaginez que la table T est une table de factures, l'utilisateur X veut connaître les factures du jour et l'utilisateur Y veut créer une nouvelle facture, donc tandis que X exécute la lecture des factures, Y ne peut pas ajouter de nouvelle facture (et quand il s'agit d'argent, les gens deviennent vraiment en colère, surtout les patrons).

Je veux comprendre où nous définissons ces niveaux d'isolement: uniquement au niveau JDBC / hibernate ou dans DB également

En utilisant JDBC, vous le définissez en utilisant Connection#setTransactionIsolation .

Utilisation de Hibernate:

<property name="hibernate.connection.isolation">2</property>

  • 1: LIRE SANS ENGAGEMENT
  • 2: LIRE ENGAGÉ
  • 4: LECTURE RÉPÉTABLE
  • 8: SERIALISABLE

La configuration Hibernate est prise à partir d' ici (désolé, c'est en espagnol).

En passant, vous pouvez également définir le niveau d'isolement sur le SGBDR:

et ainsi de suite...

Luiggi Mendoza
la source
docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm Juste à ajouter pour Oracle: on peut définir le niveau d'isolement d'une transaction en utilisant l'une de ces instructions au début d'une transaction: SET TRANSACTION ISOLATION NIVEAU DE LECTURE ENGAGÉ; RÉGLER LE NIVEAU D'ISOLATION DES TRANSACTIONS SERIALISABLE; SET TRANSACTION READ ONLY;
Apprenant
2
De plus, pour économiser le coût de mise en réseau et de traitement du début de chaque transaction avec une instruction SET TRANSACTION, vous pouvez utiliser l'instruction ALTER SESSION pour définir le niveau d'isolement des transactions pour toutes les transactions suivantes: ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE; ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
Apprenant
12
En ce qui concerne REPEATABLE READ - Je pense qu'un meilleur exemple pour le démontrer est le suivant: B démarre une transaction, lit des données sur un bloc de sql WHERE aField> 10 AND aField <20, ces données sont verrouillées jusqu'à la fin de la transaction. A essaie de mettre à jour ces données mais attend à cause du verrou. Maintenant, lorsque B lira à nouveau ces données dans cette même transaction, il est garanti de lire les mêmes données, car elles sont verrouillées. Corrige moi si je me trompe.
BornToCode
1
@LuiggiMendoza Comme concept général, les niveaux d'isolation sont à peu près sale Lire , non répétable Lire et lignes Phantom . Les verrous (S2PL) ou MVCC sont des implémentations pour différents fournisseurs.
thé brb le
4
@LuiggiMendoza - je n'étais pas précis, ça devrait être comme ça - les données que B lit ne sont pas modifiées, mais les sélections conséquentes faites par B pourraient renvoyer plus de lignes. C'est parce que A ne peut pas modifier les lignes déjà lues par B , jusqu'à ce que A les libère. Cependant, A peut insérer de nouvelles lignes qui qualifient la condition where (et donc la prochaine fois que A exécutera une sélection, il obtiendra un résultat différent avec plus de lignes - une lecture fantôme).
BornToCode
9

Comme le dit brb tea, cela dépend de l'implémentation de la base de données et de l'algorithme qu'ils utilisent: MVCC ou Two Phase Locking.

CUBRID (SGBDR open source) explique l'idée de ces deux algorithmes:

  • Verrouillage biphasé (2PL)

Le premier est lorsque la transaction T2 tente de modifier l'enregistrement A, elle sait que la transaction T1 a déjà changé l'enregistrement A et attend que la transaction T1 soit terminée car la transaction T2 ne peut pas savoir si la transaction T1 sera validée ou roulée arrière. Cette méthode est appelée verrouillage biphasé (2PL).

  • Contrôle d'accès concurrentiel multi-version (MVCC)

L'autre est de permettre à chacune d'elles, transactions T1 et T2, d'avoir sa propre version modifiée. Même lorsque la transaction T1 a changé l'enregistrement A de 1 à 2, la transaction T1 laisse la valeur d'origine 1 telle quelle et écrit que la version de transaction T1 de l'enregistrement A est 2. Ensuite, la transaction T2 suivante modifie l'enregistrement A de 1 à 3, pas de 2 à 4, et écrit que la version de transaction T2 de l'enregistrement A est 3.

Lorsque la transaction T1 est annulée, peu importe si le 2, la version de transaction T1, n'est pas appliqué à l'enregistrement A. Après cela, si la transaction T2 est validée, la version 3, la version de transaction T2, sera appliquée à l'enregistrement A. Si la transaction T1 est validée avant la transaction T2, l'enregistrement A passe à 2, puis à 3 au moment de la validation de la transaction T2. L'état final de la base de données est identique à l'état d'exécution de chaque transaction indépendamment, sans aucun impact sur les autres transactions. Par conséquent, il satisfait la propriété ACID. Cette méthode est appelée contrôle d'accès concurrentiel multi-version (MVCC).

Le MVCC permet des modifications simultanées au prix d'une surcharge accrue en mémoire (car il doit maintenir différentes versions des mêmes données) et en calcul (au niveau REPETEABLE_READ, vous ne pouvez pas perdre les mises à jour, il doit donc vérifier les versions des données, comme Hiberate fait avec Optimistick Locking ).

En 2PL niveaux d'isolement contrôlent les éléments suivants :

  • Indique si les verrous sont pris lors de la lecture des données et quel type de verrou est demandé.

  • Combien de temps les verrous de lecture sont maintenus.

  • Si une opération de lecture référençant des lignes modifiées par une autre transaction:

    • Bloquer jusqu'à ce que le verrou exclusif sur la ligne soit libéré.

    • Récupérez la version validée de la ligne qui existait au moment du démarrage de l'instruction ou de la transaction.

    • Lisez la modification de données non validée.

Le choix d'un niveau d'isolement des transactions n'affecte pas les verrous acquis pour protéger les modifications des données. Une transaction obtient toujours un verrou exclusif sur toutes les données qu'elle modifie et conserve ce verrou jusqu'à ce que la transaction se termine, quel que soit le niveau d'isolement défini pour cette transaction. Pour les opérations de lecture, les niveaux d'isolement des transactions définissent principalement le niveau de protection contre les effets des modifications apportées par d'autres transactions.

Un niveau d'isolation inférieur augmente la capacité de nombreux utilisateurs à accéder aux données en même temps, mais augmente le nombre d'effets de concurrence , tels que des lectures incorrectes ou des mises à jour perdues, que les utilisateurs peuvent rencontrer.

Exemples concrets de la relation entre verrous et niveaux d'isolement dans SQL Server (utilisez 2PL sauf sur READ_COMMITED avec READ_COMMITTED_SNAPSHOT = ON)

  • READ_UNCOMMITED: n'émettez pas de verrous partagés pour empêcher d'autres transactions de modifier les données lues par la transaction en cours. Les transactions READ UNCOMMITTED ne sont pas non plus bloquées par des verrous exclusifs qui empêcheraient la transaction actuelle de lire les lignes qui ont été modifiées mais non validées par d'autres transactions. [...]

  • READ_COMMITED:

    • Si READ_COMMITTED_SNAPSHOT est défini sur OFF (valeur par défaut): utilise des verrous partagés pour empêcher d'autres transactions de modifier les lignes pendant que la transaction en cours exécute une opération de lecture. Les verrous partagés empêchent également l'instruction de lire les lignes modifiées par d'autres transactions jusqu'à ce que l'autre transaction soit terminée. [...] Les verrous de ligne sont libérés avant que la ligne suivante ne soit traitée. [...]
    • Si READ_COMMITTED_SNAPSHOT est défini sur ON, le moteur de base de données utilise la gestion des versions de ligne pour présenter chaque instruction avec un instantané cohérent sur le plan transactionnel des données telles qu'elles existaient au début de l'instruction. Les verrous ne sont pas utilisés pour protéger les données des mises à jour par d'autres transactions.
  • REPETEABLE_READ: des verrous partagés sont placés sur toutes les données lues par chaque instruction de la transaction et sont conservés jusqu'à la fin de la transaction.

  • SERIALIZABLE: les verrous de plage sont placés dans la plage de valeurs de clé qui correspondent aux conditions de recherche de chaque instruction exécutée dans une transaction. [...] Les verrous de plage sont maintenus jusqu'à ce que la transaction se termine.

Gabrielgiussi
la source
5

Les verrous sont toujours pris au niveau DB: -

Document officiel d'Oracle: - Pour éviter les conflits lors d'une transaction, un SGBD utilise des verrous, des mécanismes pour bloquer l'accès par d'autres aux données auxquelles la transaction accède. (Notez qu'en mode de validation automatique, où chaque instruction est une transaction, les verrous sont maintenus pour une seule instruction.) Une fois qu'un verrou est défini, il reste en vigueur jusqu'à ce que la transaction soit validée ou annulée. Par exemple, un SGBD pourrait verrouiller une ligne d'une table jusqu'à ce que ses mises à jour aient été validées. L'effet de ce verrouillage serait d'empêcher un utilisateur d'obtenir une lecture incorrecte, c'est-à-dire de lire une valeur avant qu'elle ne soit rendue permanente. (L'accès à une valeur mise à jour qui n'a pas été validée est considéré comme une lecture incorrecte, car il est possible que cette valeur soit restaurée à sa valeur précédente. Si vous lisez une valeur qui est ultérieurement restaurée, vous aurez lu une valeur non valide. )

La façon dont les verrous sont définis est déterminée par ce que l'on appelle un niveau d'isolement des transactions, qui peut aller de la non prise en charge des transactions du tout à la prise en charge des transactions qui appliquent des règles d'accès très strictes.

Un exemple de niveau d'isolement de transaction est TRANSACTION_READ_COMMITTED, qui ne permettra pas d'accéder à une valeur tant qu'elle n'a pas été validée. En d'autres termes, si le niveau d'isolement des transactions est défini sur TRANSACTION_READ_COMMITTED, le SGBD n'autorise pas les lectures modifiées. L'interface Connection comprend cinq valeurs qui représentent les niveaux d'isolement des transactions que vous pouvez utiliser dans JDBC.

Goyal Vicky
la source