Add transaction course (first part)
This commit is contained in:
parent
b648ca914d
commit
05b143ac2f
2 changed files with 576 additions and 0 deletions
162
content/bdd_avancees/7-transactions/index.md
Normal file
162
content/bdd_avancees/7-transactions/index.md
Normal file
|
@ -0,0 +1,162 @@
|
|||
---
|
||||
title: "Base de données avancées : Mise en œuvre des transactions"
|
||||
date: 2022-03-29
|
||||
tags: ["transaction"]
|
||||
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
|
||||
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 :
|
||||
|
||||
* problème systèmes: récupérabilité
|
||||
* exécution concurente de plusieurs transactions: sériabilité.
|
||||
|
||||
Le système doit garantir les propriété ACID afin de preserver la cohérence des
|
||||
données :
|
||||
|
||||
* Atomicité: soit **toutes** les opérations sont validées soit aucune.
|
||||
* Cohérence: l'exécution d'une transaction jusqu'à sa validation doit laisser
|
||||
la base dans un **état cohérent**.
|
||||
* Isoliation: les transactions qui s'exécutent en concurence sont isolées les
|
||||
unes des autres. Les modification effectuée par l'une ne doivent pas être
|
||||
prise en comptes par une autre.
|
||||
* Durabilité: si une transaction est validée, les modification qu'elle a
|
||||
apportée à la base sont **persitantes**, même après le redémarrage du
|
||||
service, une coupure de courant ou un crash
|
||||
|
||||
## L'exemple de la banque
|
||||
|
||||
Prenons un exemple de virement de 1000 euros d'un compte A vers un compte B:
|
||||
|
||||
1. Lire(A)
|
||||
2. A = A - 1000
|
||||
3. Ecrire(A)
|
||||
4. Lire B
|
||||
5. B - B + 1000
|
||||
6. Ecrire(B)
|
||||
|
||||
Une fois la transaction terminée et validée, elle est réputée **durable**. Si
|
||||
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/
|
||||
|
||||
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.
|
||||
|
||||
## État d'une transaction
|
||||
|
||||
Une transaction peut avoir 5 états:
|
||||
|
||||
* Active: c'est une transaction en cours d'exécution
|
||||
* Partiellement validée: entre la dernière action et la validation
|
||||
* Échec: lorque l'exécution normale de la transaction ne peut avoir lieu
|
||||
* Avortée: après que toutes les modifications faite par la transaction soient
|
||||
annulées (rollback). Il est alors possible de réexécuter la transaction ou de
|
||||
la supprimer.
|
||||
* Validée: après l'exécution réussie de la dernière opération.
|
||||
|
||||

|
||||
|
||||
## Implémentation de l'atomicité
|
||||
|
||||
### Approche naïve
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
base est volumineuse.
|
||||
|
||||
### L'exécution concurrente
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
##### Ordonnancement en série
|
||||
|
||||
Soit \\(T_1\\) et \\(T_2\\) deux transactions ordonancées par \\(O_1\\), en
|
||||
série \\(T_2\\) sera exécutée lorsque \\(T_1\\) sera terminée.
|
||||
|
||||
##### 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
|
||||
d'ordonnancement \\(O_2\\):
|
||||
|
||||
|
||||
\\( \begin{array}{l|l}
|
||||
T_1 & T_2 \\\
|
||||
lire(A) & \\\
|
||||
A := A + 1000 &\\\
|
||||
ecrire(A) &\\\
|
||||
& lire(A) \\\
|
||||
& tmp := A * 0.2 \\\
|
||||
& A := A - tmp \\\
|
||||
& ecrire(A) \\\
|
||||
lire(B) & \\\
|
||||
B := B + 1000 & \\\
|
||||
ecrire(B $ \\\
|
||||
& lire(B) \\\
|
||||
& B = B + tmp \\\
|
||||
& ecrire(B) \\\
|
||||
\end{array}
|
||||
\\)
|
||||
|
||||
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é
|
||||
|
||||
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
|
||||
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
|
||||
sérialisable si toutes les permutations possibles ne changent pas le résultat.
|
||||
Il faut don tester \\(n!\\) possibilités de permutations.
|
||||
|
||||
Pour tester et trouver le bon ordonnancement, nous avons à notre disposition la
|
||||
c-sériabilité.
|
||||
|
||||
##### 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\\):
|
||||
|
||||
* ne sont **pas en conflit** si elles accèdent toutes des deux à \\(Q\\) en
|
||||
lecture
|
||||
* sont **en conflit** si l'une des deux (ou les deux) accède à \\(Q\\)en
|
||||
écriture
|
||||
|
||||
Si notre ordonnancement \\(O_n\\) peut-être transformé en \\(O_n^'\\) par une
|
||||
série de remplacement d'instructions non conflictuelle alors \\(O_n\\) et
|
||||
\\(O_n^'\\) sont dit **c-équivalent**. \\(O_n\\) est c-sérialisable s'il est
|
||||
c-équivalent à un ordonnancement en série.
|
Loading…
Add table
Add a link
Reference in a new issue