162 lines
6 KiB
Markdown
162 lines
6 KiB
Markdown
---
|
|
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.
|