|
|
|
Bases de données
|
R. Charrier / G. Simon / B. Sadeg
|
<<<<< Transactions pgSQL :
comprendre le fonctionnement d'une transaction >>>>>
|
- Définitions
- Définition 1 : Une transaction est un ensemble de
requêtes et d'actions qui permet de passer d'un état cohérent de la
base de données à un autre état cohérent.
- Définition 2 : Dans la base, du point de vue d'un client
réalisant une
suite d'opérations, il est souhaitable que les
différentes opérations de cette séquence
apparaissent comme une opération unique (donc que les
différentes opérations apparaissent comme étant
exécutées simultanément). Une séquence
d'instructions possédant cette propriété est dite atomique et est appelée transaction (atomique).
Pour la plupart des questions,
utiliser deux terminaux avec dans chacun une connexion différente
à
Ces deux terminaux seront nommés xterm1 et xterm2 dans la suite.
- Question 1 : connexions
multiples sans transaction explicite
- Dans le xterm1, taper la commande suivante :
INSERT INTO produit (np, lib, coul, qs) VALUES(50, 'feuilles','blanche', 100000); |
- Dans chacun des deux xterms, taper la commande suivante :
SELECT * FROM PRODUIT;
|
La modification de la table produit est visible dans
les deux cas |
- étape 1 -> dans le xterm 1 :>
SELECT * from produit;
BEGIN transaction;
INSERT INTO produit (np, lib, coul, qs) VALUES(50, 'feuilles','blanche', 100000);
SELECT * from produit;
|
la
modification est visible lors du deuxième select
|
>
- étape 2 -> dans le xterm2 :
SELECT * from produit;
|
la modification de la table produit
n'apparaît pas. |
- étape 3 -> retour au xterm1 :
COMMIT transaction;
|
le
commit valide toutes les requêtes depuis le début de la
transaction.
les modifications deviennent donc persistantes dans la base de
données.
|
- étape 4 -> à nouveau dans le xterm2 :
SELECT * from produit;
|
la modification de la table produit est bien
visible maintenant.
|
- Question 3 : Annulation
de transaction par rollback
Recommencer le
même scénario que dans la question 2 mais en
remplaçant COMMIT par ROLLBACK à l'étape 3.
Que constatez-vous ?
Dans cette question, on ne travaille
qu'avec une seule connexion sur la base de données.
Soient les tables achat(np, ncli, qa) et produit(np, lib, couleur, qs)
Si un nouvel achat est
effectué (exemple : le client
101 a acheté 55 articles du produit 3), il faudra faire deux
actions :
1) insérer cet achat dans
la table Achat.
2) décrémenter le
stock du produit 3 de la
quantité achetée dans la table produit (ici 55).
Cette contrainte avait
été précédemment traitée par
l'introduction d'un trigger
qu'il faut SUPPRIMER pour
ce tp.
Pour une raison de cohérence
des données, on ne peut pas faire la première action sans
être certain que la deuxième action sera faite !
Les deux requêtes SQL
doivent donc être considérées par le SGBD comme une
seule opération. Pour ce faire, une transaction va être
utilisée.
question
4.1 : écrire la transaction permettant de
réaliser un nouvel achat (vous prendrez un exemple
cohérent avec vos données).
question
4.2 : tant que le commit n'a pas été fait, quelle
est la quantité en stock pour les autres utilisateurs ?
Dans les questions 5,6 et 7, on va de nouveau travailler avec deux
connexions dans deux xterms différents. Mais on va cette fois
manipuler deux transactions en parallèle.
- Question 5 : Transactions concurrentes - insert+select
transaction
1 (xterm1)
|
transaction
2
(xterm2) |
begin transaction;
|
begin transaction; |
insert into client(ncli,nom) values
(120,'WOOLDRIDGE');
|
... on attend... |
select * from client;
|
... on attend ...
|
... on attend... |
select * from client; |
commit transaction;
|
... on attend ...
|
... on attend ... |
select * from client;
|
... on attend ...
|
commit transaction; |
Que constatez-vous ?
- Question 6 : Transactions concurrentes - 2 update sur le
même tuple
transaction
1 (xterm1)
|
transaction
2
(xterm2) |
begin transaction;
|
begin transaction; |
update client set nom =
'JENNINGS' where ncli = 120;
|
... on attend... |
select * from client;
|
... on attend ...
|
... on attend... |
select * from client; |
...
on attend ...
|
update client set nom = 'SYCARA'
where ncli = 120; |
commit transaction; |
... on attend ...
|
select * from client;
|
... on attend ...
|
... on attend ...
|
select * from client;
|
... on attend ...
|
commit transaction;
|
... on attend ...
|
select * from client;
|
Que constatez-vous ?
- Question 7 : Transactions concurrentes - Etreinte fatale
transaction 1 (xterm1)
|
transaction 2 (xterm2)
|
begin transaction;
|
begin transaction;
|
update produit set qs = 2000 where np = 50;
|
... on attend... |
... on attend ...
|
update produit set qs = 100 where np = 10;
|
... on attend... |
select * from produit;
|
select * from produit;
|
... on attend ...
|
update produit set qs = 500 where np = 10;
|
... on attend ...
|
... on attend ...
|
update produit set qs = 5000 where np = 50;
|
select * from produit;
|
... on attend ...
|
... on attend ...
|
commit transaction; |
... on attend ...
|
select * from produit;
|
commit transaction; |
... on attend ...
|
select * from produit;
|
... on attend ...
|
... on attend;
|
select * from produit;
|
Que constatez-vous ?
|