Transaction course part 2
This commit is contained in:
parent
4a9c7219f5
commit
8b18e6f085
1 changed files with 183 additions and 19 deletions
|
@ -6,13 +6,13 @@ categories: ["Base de données avancées", "Cours"]
|
|||
mathjax: true
|
||||
---
|
||||
|
||||
Une transaction est une unité d'un programme qui accède à des données d'un SGBR
|
||||
Une transaction est une unité d'un programme qui accède à des données d'un SGBDR
|
||||
en lecture, écriture ou les deux. Une transaction accède à un **état cohérent**
|
||||
de la base. Puis lors de son exécution l'état de la base **peut ne plus être
|
||||
cohérent**. Lors de sa validation (on parle de *commit*), l'état de la base
|
||||
**doit redevenir cohérent**.
|
||||
|
||||
Deux problèmes types peuvent se poser alors :
|
||||
Deux problèmes types peuvent se poser :
|
||||
|
||||
* problème systèmes: récupérabilité
|
||||
* exécution concurente de plusieurs transactions: sériabilité.
|
||||
|
@ -45,12 +45,12 @@ Une fois la transaction terminée et validée, elle est réputée **durable**. S
|
|||
elle échoue à partir de l'etape 3, il faut s'assurer que les modifications ne
|
||||
soient pas persistantes.
|
||||
|
||||
Les données sont alors **cohérente** : la somme de A est B est toujours la même/
|
||||
Les données sont alors **cohérente** : la somme de A est B est toujours la même.
|
||||
|
||||
Si une autre transaction accède à la base entre les étapes 3 et 6, elle trouvera
|
||||
la base dans un état incohérent (A + B est inférieur et 1000 euros se
|
||||
balladent...). **L'isolation** n'est pas assurée, la solution la plus simple
|
||||
consisterai alors à **serialiser** les transaction.
|
||||
consisterai alors à **sérialiser** les transactions.
|
||||
|
||||
## État d'une transaction
|
||||
|
||||
|
@ -72,8 +72,7 @@ Une transaction peut avoir 5 états:
|
|||
|
||||
Nous pouvons commencer par une approche naïve : **copie intégrale de la base
|
||||
lors d'une opération** avec gestion d'un **pointeur** qui mème vers la dernière
|
||||
version cohérente de la base. Le pointeur est modifié seulement si la
|
||||
transaction réussie.
|
||||
version cohérente. Le pointeur est modifié seulement si la transaction réussie.
|
||||
|
||||
En plus de ne permettre l'exécution d'une seule transaction (pas de gestion de
|
||||
l'exécution concurrente), cette approche est lourde et coûteuse surtout si la
|
||||
|
@ -84,24 +83,23 @@ base est volumineuse.
|
|||
Dans ce cas de figure, plusieurs transaction peuvent s'exécuter en même temps.
|
||||
Cette approche apporte une **meilleure utilisation des ressources** ( voir les
|
||||
[cours de système]({{< ref "/systemes_exploitation/1-introduction/index.md" >}}),
|
||||
ainsi on réduit le temps de réponses: une longue transaction ne bloque plus les
|
||||
ainsi on réduit le temps de réponse: une longue transaction ne bloque plus les
|
||||
autres.
|
||||
|
||||
**Le contrôle de la concurence** est le mécanisme permettant l'interaction entre
|
||||
les transaction tout en garantissant l'intégrité de la base.
|
||||
|
||||
#### Ordonnancement
|
||||
## Ordonnancement
|
||||
|
||||
Ici encore on peut se référer au cours de *système d'exploitation*, ici
|
||||
l'ordonnancement défini la manière d'exécuter les transaction de manière
|
||||
concurrente.
|
||||
Ici encore on peut se référer au cours de *système d'exploitation*.
|
||||
L'ordonnancement défini la manière d'exécuter les transactions concurrentes.
|
||||
|
||||
##### Ordonnancement en série
|
||||
### Ordonnancement en série
|
||||
|
||||
Soit \\(T_1\\) et \\(T_2\\) deux transactions ordonancées par \\(O_1\\), en
|
||||
Soit \\(T_1\\) et \\(T_2\\) deux transactions ordonnancées par \\(O_1\\), en
|
||||
série \\(T_2\\) sera exécutée lorsque \\(T_1\\) sera terminée.
|
||||
|
||||
##### Ordonnancement entrelacé
|
||||
### Ordonnancement entrelacé
|
||||
|
||||
Ici les actions réalisées par deux transaction s'exécutent de manières
|
||||
entrelacées. Soit deux transactions \((T_2\)) et \((T_3\)), voici le plan
|
||||
|
@ -130,7 +128,7 @@ Dans l'exemple ci-dessus, l'entrelassement ne préserve pas les valeurs de A et
|
|||
B. Les valeurs finales de notre version entrelacée ne correxpondent plus aux
|
||||
valeurs de la version en série. **Nous sommes donc face à un problème**
|
||||
|
||||
#### Notion de sériabilité
|
||||
### Notion de sériabilité
|
||||
|
||||
Dans le cas d'opération de lecture / écriture, nous partons du principe que
|
||||
chaque transaction prise à part conserve la coherence de la base. Ainsi
|
||||
|
@ -139,14 +137,14 @@ l'ordonnancement en série préserve la cohérence.
|
|||
Un ordonnancement entrelace est dit *sérialisable* si son résultat est
|
||||
**exactement le même** que s'il est exécuté en série.
|
||||
|
||||
L'ordonnancement \\(O_f\\) composé de n transaction \\(T_1, T_2, ... T_n\\) est
|
||||
L'ordonnancement \\(O_f\\) composé de n transactions \\(T_1, T_2, ... T_n\\) est
|
||||
sérialisable si toutes les permutations possibles ne changent pas le résultat.
|
||||
Il faut don tester \\(n!\\) possibilités de permutations.
|
||||
Il faut donc tester \\(n!\\) possibilités de permutations.
|
||||
|
||||
Pour tester et trouver le bon ordonnancement, nous avons à notre disposition la
|
||||
c-sériabilité.
|
||||
|
||||
##### c-seriabilité
|
||||
### c-seriabilité
|
||||
|
||||
Les instructions notées \\(t_x\\) et \\(t_y\\) des transactions \\(T_x\\) et
|
||||
\\(T_y\\) ordonnancées par \\(O_n\\) accèdent au même objet \\(Q\\):
|
||||
|
@ -159,4 +157,170 @@ Les instructions notées \\(t_x\\) et \\(t_y\\) des transactions \\(T_x\\) et
|
|||
Si notre ordonnancement \\(O_n\\) peut-être transformé en \\(O_n^\text{'}\\) par
|
||||
une série de remplacement d'instructions non conflictuelle alors \\(O_n\\) et
|
||||
\\(O_n^\text{'}\\) sont dit **c-équivalent**. \\(O_n\\) est c-sérialisable s'il
|
||||
est c-équivalent à un ordonnancement en série.
|
||||
est c-équivalent à un ordonnancement en série.
|
||||
|
||||
## Reprise sur panne, récupérabilité
|
||||
|
||||
un Ordonnancement \\(O\\) est récupérable si à la suite de l'annulation d'une de
|
||||
ses transactions, nous pouvons revenir à un état cohérent sans pour autant
|
||||
annuler les transaction validées.
|
||||
|
||||
Lors d'un **ordonnancement récupérable**, si \\(T_j\\) lit un objet précédement
|
||||
écrit par \\(T_i\\), la validation de \\(T_i\\) a lieu avant celle de de
|
||||
\\(T_j\\). Dans le cadre d'un *ordonnancement en série* le problème se se pose
|
||||
pas, mais comme nous l'avons vu c'est une méthode inefficace, surtout sans le
|
||||
cas d'achitecture multi-cœurs / multi-proceseurs.
|
||||
|
||||
C'est au SGBD de s'assurer de la récupérabilité des ordonnancements, mais cette
|
||||
tâche parfois difficile, prenons l'exemple simple suivant:
|
||||
|
||||
|
||||
\\( \begin{array}{l|l}
|
||||
t_1 & t_2 \\\
|
||||
lire(a) & \\\
|
||||
a := a + 1000 &\\\
|
||||
ecrire(a) &\\\
|
||||
& lire(a) \\\
|
||||
ecrire(b) & \\\
|
||||
... & ... \\\\
|
||||
\end{array}
|
||||
\\)
|
||||
|
||||
Si \\(T_1\\) doit être annulée, alors la valeur de \\(A\\) pourrait-être dans un
|
||||
état incohérent lorsque \\(T_1\\) y accède. Le SGBDR doit alors positionner le
|
||||
curseur entre **ordonnancement** (réactivité, utilisation des ressources) et
|
||||
**récupérabilité**.
|
||||
|
||||
Pour deux transactions \\(T_i\\), \\(T_j\\),si \\(T_j\\) accède une donnée
|
||||
écrite précédement par \\(T_i\\) alors cette dernière doit être validée en
|
||||
premier.
|
||||
|
||||
L'échec d'une transaction peut entrainer des annulations en cascade, dans
|
||||
l'exemple suivant \\(T_2\\) et \\(T_3\\) doivent être annulé:
|
||||
|
||||
\\( \begin{array}{l|l}
|
||||
t_1 & t_2 & t_3\\\
|
||||
lire(a) & & \\\
|
||||
a := a + 1000 & &\\\
|
||||
ecrire(a) & &\\\
|
||||
& lire(a) & \\\
|
||||
& & lire(a) \\\
|
||||
ecrire(b) & & \\\
|
||||
... & ... & ... \\\
|
||||
\end{array}
|
||||
\\)
|
||||
|
||||
Un ordonnancement sans cascade est récupérable, il est donc préférable de
|
||||
limiter les ordonnancement entrelacé à ceux sans cascade.
|
||||
|
||||
### tester la c-sériabilité
|
||||
|
||||
Considérons un ordonnancement \\(O\\) avec les transactions \\(T_1, T_2, ...
|
||||
T_n\\) :
|
||||
|
||||
* \\(n\\) est l'ensemble des transactions
|
||||
* il y a un arc \\((T_i, T_j)\\) s'il y a conflit entre ces deux transactions
|
||||
sur un object \\(Q\\), \\(T_i\\) accède à \\(Q\\) avant \\(T_j\\).
|
||||
|
||||
Alors \\(O\\) est *c-serialisable* si son graphe de précédence est acyclique.
|
||||
|
||||
\\( \begin{array}{l|l|l|l|l}
|
||||
t_1 & t_2 & t_3 & t_4 & t_5\\\
|
||||
& lire(x) & & & \\\
|
||||
lire(y) & & & & \\\
|
||||
lire(z) & & & & \\\
|
||||
& & & & lire(v) \\\
|
||||
& & & & lire(w) \\\
|
||||
& & & & ecrire(w) \\\
|
||||
& lire(y) & & & \\\
|
||||
& ecrire(y) & & & \\\
|
||||
& & ecrire(z) & & \\\
|
||||
lire(u) & & & & \\\
|
||||
& & & lire(y) & \\\
|
||||
& & & ecrire(y) & \\\
|
||||
& & & lire(z) & \\\
|
||||
& & & ecrire(z) & \\\
|
||||
lire(u) & & & & \\\
|
||||
ecrire(u) & & & \\\
|
||||
\end{array}
|
||||
\\)
|
||||
|
||||
|
||||

|
||||
|
||||
Tester si l'ordonnancement est sérialisable après son exécution
|
||||
ou sur son graphe de précédence est inefficace. Le but ici est donc de
|
||||
développer des statégies de contrôle de la concurence qui puissent garantir la
|
||||
c-sériabilité. Il ne sera pas question de faire des tests sur le grahe de
|
||||
précédence mais plutôt les mécanisme de verrouillage que nous verrons un peu
|
||||
plus bas.
|
||||
|
||||
## contrôle de la concurrence
|
||||
|
||||
### notion de verrouillage
|
||||
|
||||
Lorsque une transaction accède à une donnée, elle pose un verrou dessus, il
|
||||
existe deux type de verrous:
|
||||
|
||||
* **exclusif**: la transaction qui pose se verrou peux *lire* et *écrire* la
|
||||
donnée. Le verrou `X` est alors attribué à l'exécution via la commande
|
||||
`Lock_X(data)`
|
||||
* **partagé**: la transaction ne peut que *lire* la donnée. Le verrou `P` est
|
||||
attribué via la commande `Lock_P(data)`
|
||||
|
||||
C'est le rôle du **gestionnaire de concurrence** de gérer l'attribution des
|
||||
verrous à la demande des transaction. Il défini le protocole de verrouillage :
|
||||
commend demander et libérer les verrous. Cette dernière ne peut avancer tant
|
||||
que le verrou demandé ne lui a pas été attribué.
|
||||
|
||||
Une transaction ne peut poser un verrou sur une donnée qui si celui-ci est
|
||||
compatible avec le verrou déjà en place (s'il y en a un bien entendu).
|
||||
|
||||
Une transaction peut libérer certain verrou avec la commande `Unlock()`.
|
||||
|
||||
### Gestion de l'interblocage (deadlock)
|
||||
|
||||
Comme nous l'avons vu pour les [Mecanisme de synchronisation]({{< ref
|
||||
"/systemes_exploitation/3-synchronisation/index.md" >}}), dès qu'il y a verrou
|
||||
il y a risque d'interblocage. Les transaction n'échappent pas à la règle.
|
||||
|
||||
### Protocole de verrou à deux phases
|
||||
|
||||
Ce protocole permet de garantir la *c-sériabilité*
|
||||
|
||||
* **phase 1**: pose de verrous, il est interdit d'en libérer.
|
||||
* **phase 2**: libération des verrou, il est interdit d'en poser.
|
||||
|
||||
### protocole avec estampille
|
||||
|
||||
C'est un protocole avec la gestion d'une file d'attente en fonction de l'heure
|
||||
d'arrivée: l'ordre chronologique des transactions.
|
||||
|
||||
### granularité des verrouillage
|
||||
|
||||
Le verroullage peut se faire à plusieurs niveau organisés hiérachiquement:
|
||||
|
||||
1. la base
|
||||
2. une table
|
||||
3. une page
|
||||
4. un tuple
|
||||
|
||||
Une transaction verrouiller n'importe quel niveau en fonction de ses besoins.
|
||||
|
||||
### gestion des blocages
|
||||
|
||||
Le SGBDR peut intervenië sur deux niveaux : **prévenir** et *guérir*
|
||||
|
||||
#### prévenir
|
||||
|
||||
Il est question ici d'éviter les situations de blocage. L'estampille joue un
|
||||
rôle crutial : la gestion des transaction se fait en fonction de son horodatage
|
||||
(privilegier les plus anciennes)
|
||||
|
||||
#### guérir
|
||||
|
||||
Pour guérir mous pouvons
|
||||
|
||||
1. détecter les blocages à l'aide de graphe précédence
|
||||
2. choisir d'ue transaction à annuler, en général celle la plus loin de son
|
||||
état final.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue