web-dev-qa-db-fra.com

Relation entre les niveaux d'isolation des transactions et les verrous de la table

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 isolement 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)

ci-dessous sont les trois phénomènes qui peuvent se produire dans l'isolement de transaction
Dirty Read- pas de verrou
Lecture non répétable - pas de lecture sale comme verrou sur les données validées
Lecture fantôme - verrouiller le bloc de SQL (qui est sélectionné en utilisant la requête select)

Je veux comprendre où nous définissons ces niveaux d'isolement: uniquement au niveau jdbc/hibernate ou dans la base de données également

PS: Je suis passé par les liens dans niveaux d’isolation dans Oracle , mais ils ont l’air maladroit et parlent de bases de données spécifiques

93
Java Geek

Je veux comprendre le verrou que chaque isolement 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 (en fonction des résultats). B exécute simplement une instruction SELECT pour lire les données. C lit et met à jour les données. Tous ces processus fonctionnent sur la même table T.

  • READ UNCOMMITTED - pas de verrou sur la table. Vous pouvez lire des données dans la table en écrivant dessus. Cela signifie que A écrit des données (non validées) et que B peut lire ces données non validées et les utiliser (à quelque fin que ce soit). Si A exécute une restauration, B a toujours lu les données et les a utilisées. Il s’agit du moyen le plus rapide mais le moins sûr de travailler avec des données car il peut en résulter des lacunes dans les tableaux non liés physiquement (oui, deux tableaux peuvent être logiquement mais non liés physiquement dans les applications du monde réel = \).
  • READ COMMITTED - verrouille les données validées. Vous pouvez lire les données qui ont été validées uniquement. Cela signifie que A écrit les données et que B ne peut pas lire les données enregistrées par A tant que A n’a pas exécuté de validation. Le problème ici est que C peut mettre à jour les données qui ont été lues et utilisées sur le client B et B ne disposeront pas des données mises à jour.
  • REPEATABLE READ - verrouille un bloc de code SQL (sélectionné à l'aide de la requête select). Cela signifie que B lit les données sous certaines conditions, à savoir WHERE aField > 10 AND aField < 20, A insère des données où aField valeur est comprise entre 10 et 20, puis B relit les données et obtient un résultat différent.
  • [~ # ~] sérialisable [~ # ~] - verrouille une table complète (sur laquelle la requête Select est déclenchée). Cela signifie que B lit les données et 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 entraîner de gros problèmes en production: imaginez que la table T soit une table de facturation, l'utilisateur X souhaite pour connaître les factures du jour et l'utilisateur Y veut créer une nouvelle facture. Ainsi, bien que X exécute la lecture des factures, Y ne peut pas ajouter de nouvelle facture (et lorsqu'il s'agit d'argent, les gens deviennent vraiment fous, en particulier les chefs ).

Je veux comprendre où nous définissons ces niveaux d'isolement: uniquement au niveau JDBC/hibernate ou dans la base de données également

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

Utiliser Hibernate:

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

  • 1: LIRE NON ENGAGÉ
  • 2: LIRE ENGAGÉ
  • 4: Lecture répétée
  • 8: sérialisable

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

En passant, vous pouvez également définir le niveau d’isolation sur le SGBDR:

et ainsi de suite...

139
Luiggi Mendoza

Comme le dit brb tea, cela dépend de l'implémentation de la base de données et de l'algorithme utilisé: 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 essaie de modifier l'enregistrement A, il 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 lancée. retour. Cette méthode s'appelle le verrouillage biphasé (2PL).

  • Contrôle de simultanéité multi-version (MVCC)

L'autre consiste à autoriser chacune des transactions T1 et T2 à avoir leurs propres versions modifiées. Même lorsque la transaction T1 a modifié l'enregistrement A de 1 à 2, la transaction T1 conserve la valeur d'origine 1 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 et non 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 que la version 2, la transaction T1, ne soit pas appliquée à l'enregistrement A. Après cela, si la transaction T2 est validée, la 3, la version de la transaction T2, sera appliquée à l'enregistrement A. Si la transaction T1 est validée avant la transaction T2, l'enregistrement A est modifié en 2, puis en 3 au moment de la validation de la transaction T2. Le statut final de la base de données est identique à celui de l'exécution de chaque transaction indépendamment, sans incidence sur les autres transactions. Par conséquent, il satisfait la propriété ACID. Cette méthode est appelée contrôle de simultanéité multi-version (MVCC).

MVCC autorise des modifications simultanées au détriment de la surcharge de mémoire (car il doit conserver différentes versions des mêmes données) et de calcul (au niveau REPETEABLE_READ, vous ne pouvez pas perdre les mises à jour. Vous devez donc vérifier les versions des données, comme Hiberate. fait avec Optimistick Locking ).

Dans 2PL les niveaux d'isolation de transaction contrôlent ce qui suit :

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

  • Combien de temps les verrous de lecture sont-ils retenus?.

  • Si une opération de lecture faisant référence à 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'isolation de transaction n'affecte pas les verrous acquis pour protéger les modifications de données. Une transaction obtient toujours un verrou exclusif sur toutes les données qu'elle modifie et le conserve jusqu'à la fin de la transaction, quel que soit le niveau d'isolement défini pour cette transaction. Pour les opérations de lecture, les niveaux d'isolation de transaction définissent principalement le niveau de protection contre les effets des modifications apportées par d'autres transactions.

Un niveau d'isolement inférieur augmente la capacité de nombreux utilisateurs à accéder aux données simultanément, mais augmente également le nombre d'effets de concurrence , tels que les lectures non conformes ou les pertes. mises à jour, que les utilisateurs peuvent rencontrer.

Exemples concrets de la relation entre les verrous et les niveaux d'isolation 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 empêchant la transaction en cours de lire des lignes modifiées mais non validées par d'autres transactions. [...]

  • READ_COMMITED:

    • Si READ_COMMITTED_SNAPSHOT est défini sur OFF (par défaut): utilise des verrous partagés pour empêcher d'autres transactions de modifier des 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 le traitement de la ligne suivante. [...]
    • Si READ_COMMITTED_SNAPSHOT est défini sur ON, le moteur de base de données utilise le contrôle de version de ligne pour présenter chaque instruction avec un instantané cohérent pour les transactions, tel qu'il existait 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é correspondant aux conditions de recherche de chaque instruction exécutée dans une transaction. [...] Les verrouillages de gamme sont conservés jusqu'à la fin de la transaction.

8
gabrielgiussi

Les verrous sont toujours pris au niveau de la base de données: -

Document officiel Oracle: - Pour éviter les conflits lors d’une transaction, un SGBD utilise des verrous, des mécanismes permettant de bloquer l’accès de tiers aux données auxquelles la transaction accède. (Notez qu'en mode de validation automatique, où chaque instruction est une transaction, les verrous ne sont maintenus que pour une seule instruction.) Une fois le verrou défini, il reste en vigueur jusqu'à ce que la transaction soit validée ou annulée. Par exemple, un SGBD peut verrouiller une ligne d'une table jusqu'à ce que ses mises à jour aient été validées. Ce verrouillage aurait pour effet d'empêcher un utilisateur d'obtenir une lecture incorrecte, c'est-à-dire de lire une valeur avant qu'elle ne devienne permanente. (L'accès à une valeur mise à jour qui n'a pas été validée est considéré comme une lecture modifiée, 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 manière dont les verrous sont définis est déterminée par ce que l’on appelle un niveau d’isolation de transaction, qui peut aller de la non prise en charge de transactions à la prise en charge de transactions appliquant des règles d’accès très strictes.

TRANSACTION_READ_COMMITTED est un exemple de niveau d'isolation de transaction. Il ne permet pas d'accéder à une valeur tant qu'elle n'a pas été validée. En d'autres termes, si le niveau d'isolation de transaction est défini sur TRANSACTION_READ_COMMITTED, le SGBD n'autorise pas les lectures modifiées. La connexion d'interface comprend cinq valeurs représentant les niveaux d'isolation de transaction que vous pouvez utiliser dans JDBC.

4
Goyal Vicky