Transactions
2 9. Les Transactions
Service (ACID) garanti "malgré" le parallélisme de l'accès aux requêtes
Atomicité : Toutes les requêtes de la transaction ou aucunes,
Cohérence : Une transaction fait passer la base d'un état cohérent à un autre,
Clients Isolation : Une transaction n'est pas affectée par le résultat des autres transactions,
Durabilité : Les modifications dues à une transaction sont durablement garanties.
SGBD
Requêtes concurrentes = travaillant sur les mêmes données
Inconvénients du transactionnel :
• Nécessite un mode connecté (éventuellement contradictoire avec d'autres applications)
• Nécessite la disponibilité de tous les éléments inclus dans la transaction sous peine de rejet ou
d'un effondrement des performances (Serveur à haute disponibilité)
• Complexité technique + complexité de déploiement.
3 9.1 Transactions (en jdbc)
Dans beaucoup d'applications il est nécessaire de regrouper un ensemble d'instructions :
devant réussir ou échouer de manière globale
accédant de manière concurrentielle aux données
=> Transactions.
Par défaut toute instruction SQL est une transaction. Pour adapter ce modèle aux
contraintes ci-dessus il faut gérer soi-même :
• le début et la fin de la transaction ;
• le niveau d'isolation avec les autres transactions.
Avec JDBC :
Pour commencer une transaction il faut faire appel à : setAutoCommit(false), ainsi
tout ce qui sera envoyé à la BD après cette instruction sera conditionné à une
validation commit() ou à une annulation rollback();
Pour le maximum de sécurité et d'isolation entre les transactions il faut les mettre
en série. Perfs diminuées : en pratique souvent trop contraignant car pas de
parallélisme possible même en lecture.
Niveaux d'isolation :
Définies par des constantes de l'interface connection et
Positionné ou connu grâce aux méthodes de la même interface :
• setTransactionIsolation(int);
• getTransactionIsolation();
4 9.1 Transactions
Gestion programmatique des transactions par Commit et Rollback
// si req contient une requête de mise à jour
try
{
cnx.setAutoCommit(false); // début de la transaction. Pose de verrous si besoin sur les
// tables, tuples concernés !
….
Statement stmt2 = cnx.createStatement();
stmt2.executeUpdate(req);
System.out.println(« Tous les éléments sont prets »);
cnx.commit();
}
catch (Exception ex)
{
System.out.println(« un des éléments à connu une défaillance »);
cnx.rollback();
}
Finally
{
cnx.setAutoCommit(true); …. // déclenche aussi un commit implicite !
cnx.close(); }
5 9.2 Jalons intermédiaires (JDBC / Transactions)
Points de sauvegarde dans les transactions ?
La méthode rollback permet seulement d'annuler l'ensemble d'une transaction.
JDBC 3.0 utilisation de points de sauvegarde tout au long de la transaction.
Interface Savepoint du package java.sql,
Les points de sauvegarde ou Jalon permettent de revenir en arrière dans la transaction, mais
de manière ciblée.
Voici un exemple simpliste
Connection connection = ... ;
connection.setAutoCommit(false);
//une première instruction
Savepoint s1 = connection.setSavepoint("Premier point de sauvegarde");
//une deuxième instruction
Savepoint s2 = connection.setSavepoint(); // point de sauvegarde anonyme
//une troisième instruction
Savepoint s3 = connection.setSavepoint("Troisième point de sauvegarde");
connection.releaseSavepoint(s2); // on enlève le second
savepointconnection.rollback(s1); // toutes les modifications après s1 sont ignorées
connection.commit(); // seule la première instruction est validée. NE PAS OUBLIER cette
// étape, Sinon votre transaction n'est jamais validée.
6 JDBC : Transactions : isolation
TRANSACTION_NONE : pas de notion de transactions (valeur = 0)
TRANSACTION_READ_UNCOMMITTED (valeur = 1)
Garantie : aucune au niveau isolation mais possibilité de rollback.
Risque : lecture impropre (DIRTY READ), Lecture possible de données utilisées par une autre transaction
non encore validée (possibilité de rollback ou d'update)
TRANSACTION_READ_COMMITTED (Valeur = 2)
Garantie : Evite les lectures sales (ex : bloque une lecture sur des données valeur d’att sur laquelle il y a un
update)
Risque : lectures non répétables (on a pas bloqué les update les insert ou les delete)
TRANSACTION_REPEATABLE_READ (Valeur = 4)
Garantie : verrouillage en lect/ecrit des tuples concernées par les update de la transaction
Risque : lecture fantômes, on a pas bloqué les insert ou delete sur les tables concernées ;
TRANSACTION_SERIALIZABLE (Valeur = 8)
Garantie : Isolation totale
Risque : perte de performances
Synthèse
Lecture Lecture non
Niveau\Anomalie Lecture fantôme
impropre répétable
TRANSACTION_READ_UNCOMMITTED possible possible possible
TRANSACTION_READ_COMMITTED impossible Possible possible
TRANSACTION_REPEATABLE_READ impossible Impossible possible
TRANSACTION_SERIALIZABLE impossible Impossible impossible
9.3 Isolation des Transaction
8 Les Transactions
Accès concurrents
SGBD
Transaction t1 Transaction t2
Temps
Select
Select ?
stop stop
Update
stop Update ?
rollback
stop temps
Select
9 Problème d'accès concurrents
Lecture Sale (dirty read)
Une transaction lit des données écrites par une transaction concurrente non validée.
SGBD
Transaction t1 Transaction t2
T1Updater T2Reader
Temps
cnx.setAutoCommit(false); D
Début de la
transaction Update (D)
D’ Début de la
transaction
cnx.setAutoCommit(false
Lecture(D’)
La lecture faite
rollback(D’) n'a pas de sens
D puisque les temps
données sont
non validées
10 Update concurrents
Quid de deux update concurrents ?
Un update est une lecture puis une écriture (x=x+1)
Temps
SGBD
Transaction t1 Transaction t2
Début de la
Début de la
Lecture(D) transaction
transaction Lecture(D)
Update (D) D’
Update (D) bloquée en
attente de la
validation de T1
Lecture(D)
Commit() D’’ Si l’update est opérant avec D’
Commit()
MODE : READ_UNCOMMITED
Les base de données proposent différents mode d'isolation pour contrôler
les accès concurrents. Le plus bas niveau est READ_UNCOMMITED
12 Isolation des transactions Mode Read_UnCommitted
le niveau d'isolation TRANSACTION_READ_UNCOMMITTED (Valeur = 2)
Garantie : rien Principe : On peut tout lire
T1 : UPDATE et T2 : READ
‐ si une transaction t1 a démarré avant t2, que t1 a fait un update et que t2 fait
un select sur les mêmes données cibles alors t2 utilisera les données risque
modifiées par t1. Or t1 ne les a pas encore committed ; lecture
sale
T1 : UPDATE et T2 : UPDATE
‐ si une transaction t1 a démarré avant t2, que t1 a fait un update sur un tuple
et que t2 cherche aussi à faire une update sur ces données alors t2 sera
bloquée dans l'attente de la fin de t1 ; (l'update doit concerner les données
avant l'udpate de t1 pour être bloquant)
‐ si par la suite t1 committe sa transaction alors t2 est débloqué avec le lecture
risque de différence entre le select des données committed avant t1 et non
celles lues après le commit de t1, répétable
T1 : INSERT ou DELETE et T2 : READ ou UPDATE
‐ si une transaction t1 a démarré avant t2 et que t1 fait un insert ou un delete lecture
sur un ensemble de données sur lesquelles t2 cherche aussi à faire un select fantome
alors t2 ne sera pas bloquée et elle lira les "nouvelles " données ;
13 Isolation des transactions en Read_UnCommitted
Lecture Sale (dirty read)
déjà vu en intro : une transaction lit des données écrites par une transaction
concurrente non validée.
SGBD
Transaction t1 Transaction t2
Temps
Début de la
transaction Update (D)
Début de la
D’
transaction
Lecture(D’)
La lecture faite
n'a pas de sens
rollback(D’) puisque les
temps
données sont
D non validées
14 Isolation des transactions en Read_UnCommitted
Concurrence d'update dans le mode read_uncommitted
Temps
SGBD
Transaction t1 Transaction t2
Début Lecture(D)
transaction Lecture(D) Début
Update (D) transaction
D’ Update (D)
commit(D’) l'update sur données non
committed de T1 = blocage
D’’ fin de l'update
Lecture(D’’)
MODE : READ_COMMITED
16 Isolation des transactions en Read_Committed
le niveau d'isolation TRANSACTION_READ_COMMITTED (Valeur = 2)
Principe : On ne lit que des données committed :
Quand une transaction se déroule sur ce niveau, une instruction voit uniquement
les données commited avant le commencement de cette instruction; elle ne voit
ni des données en cours de modification ni des modifications commited durant
l'exécution de cette instruction
Garantie : Evite les lectures sales (ex : bloque un update sur des valeurs
d’attributs sur lesquels un update est en cours)
17 Isolation des transactions en Read_Committed
T1 : UPDATE et T2 : READ
‐ si une transaction t1 a démarré avant t2 et que t1 a fait un update sur les
mêmes données cibles alors t2 utilisera les données qui étaient committed
avant le démarrage de t1 ; (donc pas de lecture sale)
T1 : UPDATE et T2 : UPDATE
‐ si une transaction t1 a démarré avant t2, que t1 a fait un update sur
un tuple et que t2 cherche aussi à faire une update sur ces données
alors t2 sera bloquée en attente que t1 commite ses données ; (donc
pas de lecture sale)
‐ si par la suite t1 commite sa transaction alors t2 est débloqué
avec le risque de différence entre le select des données lecture non
committed avant t1 et celles apprès le commit de t1, répétable
T1 : INSERT ou DELETE et T2 : READ ou UPDATE
‐ si une transaction t1 a démarré avant t2 et que t1 fait un insert ou un lecture
delete sur un ensemble de données sur lesquelles t2 cherche aussi à fantome
faire un select alors t2 ne sera pas bloquée et elle lira les "nouvelles "
données ;
18 en mode Read_Committed
Plus de lecture sale
Temps
SGBD
Transaction t1 Transaction t2
D
Début Lecture(D) Début transaction
transaction D
Update (D)
D’ Lecture(D) comme les données ne
sont pas committed la
lecture utilise les
données avant t1
commit()
D' Lecture(D')
19 en mode Read_Committed
Plus de lecture sale MAIS Problème de la lecture Non Répétable et des
lectures fantômes
Une transaction relit des données pourtant bien committed et n'obtient pas le même résultat
Temps
SGBD
Transaction t1 Transaction t2
D
Début Lecture(D) Début transaction
transaction D
Update (D)
D’ Lecture(D) comme les données ne
Insert (D’’) sont pas committed la
lecture produit les
Delete (D’’’) données avant t1
commit() comme les données sont
Lecture(D’’’)
committed la lecture
produit après l'update de
t1 : différentes de la
Sera sensible aux tuples supprimée ou première lecture =
ajoutés Lecture fantomes Lecture non répétable
20 en mode READ_COMMITTED
quid des update concurrents ?
Temps
SGBD
Transaction t1 Transaction t2
Début de la
transaction Lecture(D) Début de la
transaction
Update (D) D’
Update (D) bloquée en attente
de la validation de T1
Lecture(D’)
ne modifiera la BD que
commit() Update (D) si l’update porte sur D’
commit()
MODE : REPEATABLE_READ
22 Isolation des transactions Mode Repeatable_Read
le niveau d'isolation TRANSACTION_REPEATBLE_READ(Valeur = 4)
Principe : On embarque dans la transaction les données récupérées à la
première lecture
Ce niveau est différent de Read Committed parce qu'une requête dans une
transaction repeatable read voit un instantané au début de la transaction, et
non pas du début de la requête en cours à l'intérieur de la transaction.
Les commandes SELECT successives à l'intérieur d'une
seule transaction voient toujours les mêmes données,
c'est‐à‐dire qu'elles ne voient jamais les modifications
faites par les autres transactions qui ont validé après le
début de leur propre transaction
23 Isolation des transactions Mode Repeatable_Read
le niveau d'isolation TRANSACTION_REPEATBLE_READ(Valeur = 4)
T1 : UPDATE et T2 : READ
‐ si une transaction t1 a démarré avant t2 et que t1 a fait un update sur les
mêmes données cibles alors t2 utilisera les données qui étaient
committed avant le démarrage de t1 ; (donc pas de lecture sale)
T1 : UPDATE et T2 : UPDATE
‐ si une transaction t1 a démarré avant t2, que t1 a fait un update sur un tuple et
que t2 cherche aussi à faire une update sur ces données alors t2 sera bloquée en
attente que t1 commit ses données ; (donc pas de lecture sale)
‐ si par la suite t1 "committe" sa transaction alors t2 est débloquée MAIS un
nouveau select produira les mêmes données que le premier de cette
transaction (donc pas de lecture non répétable)
T1 : INSERT ou DELETE et T2 : READ ou UPDATE
‐ si une transaction t1 a démarré avant t2 et que t1 fait un insert ou un lecture
delete sur un ensemble de données sur lesquelles t2 fait des select (avant fantome
et après les modifications des t1, alors t2 ne sera pas bloquée et elle
produire des résultats différents ;
24 en mode Repeatabale_Read
on évite la lecture non répétable
Temps
SGBD
Transaction t1
Transaction t2
Embarque une copie de D D
Lecture(D) D
Début
transaction Début transaction
Update (D)
D’ Lecture(D)
D
commit()
D’ Update(D)
D’’
Lecture(D’’)
D’’
commit() En BD on D’’ que si l’update
de t2 fonctionne avec D’
25 en mode Repeatabale_Read
on évite la lecture non répétable
Temps
SGBD
Transaction t1
Transaction t2
Embarque une copie de D D
Lecture(D) D
Début
transaction Début transaction
Update (D)
D’ Lecture(D) comme les données ne
D sont pas committed au
démarrage de t2,
elle embarque ses
commit() propres données (celles
avant t1)
D’ D’’ Update(D)
Lecture(D’’) Produit les
mêmes données
commit() que la première
lecture
26 en mode Repeatabale_Read
Plus de lecture non répétable MAIS lecture fantôme persiste
SGBD
Transaction t1
Transaction t2
Embarque une copie de D D
Lecture(D) D
Début
transaction Début transaction
Lecture(D)
Insert (D’’) D
J'ai lu des données
Delete (D’’’) validées mais obtenu de
nouveaux tuples ou je
n'obtiens plus les anciens
commit() Lecture(D’’’)
D’’’
Sera sensible aux tuples supprimés
ou ajoutés Lecture fantômes
27 en mode REPEATABLE_READ
Quid de deux update concurrents ?
Temps
SGBD
Transaction t1 Transaction t2
Début de la
transaction Lecture(D) Début de la
transaction
Update (D) bloquée
en attente
de la
Lecture(D) validation
de T1
commit() Update (D)
commit()
MODE : SERIALIZABLE
29 en mode Serializable
le niveau d'isolation TRANSACTION_SERIALIZABLE(Valeur = 6)
pas de concurrence d’accès
Pas d’accès concurrents entre maj et lecture
Temps
SGBD
Transaction t1 Transaction t2
D
Début Lecture(D) Début transaction
D
transaction
Update (D)
D’
Lecture(D)
commit() D’
30 en mode Serializable
on évite les lectures fantômes
Temps
SGBD
Transaction t1 Transaction t2
Début
Lecture(D)
Début
Update (D)
Insert (D’')
Produit les mêmes
données que la Lecture(D) commit()
première lecture
D commit()
31 en mode Serializable
Quid de deux update concurrents ?
SGBD
Temps
Transaction t1 Transaction t2
Début de la Lecture(D)
transaction
Début de la
Update (D)
transaction
D’
Update (D)
bloquée en attente de
la validation de T1
Lecture(D’)
Commit() Si les données en base répondent
Update (D)
encore à la condition
Commit()