Vous êtes sur la page 1sur 4

ENI RV

Transactions dans un SGBD relationnel

1. Introduction Cohérence : la transaction doit faire passer la


base de données d'un état cohérent à un autre
Une transaction est un ensemble d'actions état. En cas d'échec , l'état courant cohérent initial
atomiques permettant de prendre une base doit être restauré.
donnée dans un état cohérent et de la rendre Isolation : les résultats d'une transaction ne
dans un état cohérent. Il s'agit d'éviter par doivent être visibles aux autres transactions
exemple que l'on puisse lire une information que qu'une fois la transaction validée , ceci afin
l'on est en train de modifier par ailleurs ou de d'éviter les interférences avec les autres
mettre à jour, ou même que deux utilisateurs transactions .
mettent à jour simultanément la même Durabilité : dès qu'une transaction valide ses
information. modifications , le système doit garantir que ces
Par exemple : une transaction bancaire de modifications seront conservées en cas de panne.
transfert d'une somme S d'un compte C1 à un
autre compte C2 ( on enlève sur un compte, on 2.Mise en œuvre d'une transaction dans
dépose sur l'autre.) MySQL par
BEGIN/COMMIT/ROLLBACK
(1) Début transaction
(2) Lire (C1) // lire le compte C1 Par défaut, MySQL est lancé en mode
(3) C1=C1-S // débiter le solde de C1 autocommit . Cela signifie que chaque
(4) Ecrire (C1) modification effectué est enregistré
(5) Lire (C2) // lire le compte C2 immédiatement sur le disque par MySQL.
(6) C2=C2+S // créditer C2 Si vous utilisez des tables supportant les
(7) Ecrire (C2) transactions (comme InnoDB ), vous pouvez
(8) Fin-Transaction configurer MySQL en mode non- autocommit
grâce à la commande: SET AUTOCOMMIT=0
En supposant qu'avant l'exécution d'une telle A partir de là, vous devez utiliser COMMIT pour
transaction la base était dans un état cohérent. , enregistrer les modifications sur le disque ou
on remarque que l'exécution incomplète de cette ROLLBACK pour ignorer les modifications
transaction peut mettre la base dans un état apportées depuis le début de la transaction ( pour
incohérent , c'est à dire lorsqu' une des deux ramèner la base à l'état initial) .Si vous souhaitez
opérations échoue. Par exemple , si l'exécution sortir du mode AUTOCOMMIT pour une série
s'arrête après l'action (4) , le premier compte a d'opérations, vous pouvez utiliser les commandes
bien débité mais le second n'a pas encore crédité. BEGIN ou BEGIN WORK :
On veut que soit les deux opérations réussissent,
mais si une d'elles échoue, on annule le tout et on BEGIN;
remet les comptes dans l'état initial .On dit que les SELECT @A:=SUM(salary) FROM table1 WHERE
deux opérations forment une seule et même type=1;
transaction . UPDATE table2 SET summmary=@A WHERE
Un des avantages de la transaction est que si une type=1;
transaction s'exécute toute seule, dans une base // autres commandes de mise à jour
de données cohérente, alors elle va laisser la COMMIT ou ROLLBACK;
base de données dans un état cohérent
La transaction peut être utilisée pour résoudre le
Ainsi, chaque transaction se termine par un
problème de partage concurrent de données :
COMMIT si la transaction a réussi, ou par un
plusieurs clients consultent et modifient les
ROLLBACK qui la ramène à l'état initial si la
mêmes données et s'accorde avec les pannes
transaction échoue pour une raison ou pour une
machines ou réseau.
autre
La transaction vérifie les propriétés ACID
Mysql exige que les tables soient
(atomicité , cohérence , isolation et durabilité):
transactionnelles de type InnoDB, par exemple
CREATE TABLE Client( Nom CHAR(10),
Atomicité : une transaction doit effectuer ses
Adresse CHAR(40)) TYPE = INNODB
mises à jour ou ne rien faire du tout. En cas
d'échec , une transaction doit annuler toutes les
Avec PostgreSQL™, une transaction est réalisée
modifications qu'elle a engagées.
en entourant les commandes SQL de la

1
ENI RV

transaction avec les commandes BEGIN et ...


COMMIT. Donc, notre transaction pour la banque UNLOCK TABLES
ressemblera à ceci
LOCK TABLES verrouille une table pour le thread
BEGIN; courant. UNLOCK TABLES déverrouillera
UPDATE comptes SET balance = balance - automatiquement tous les verrous posés par le
100.00 WHERE nom = 'Alice'; thread courant.
-- etc etc L'exemple suivant necessite LOCK TABLES pour
COMMIT; s'executer en toute sécurité :
Si, au cours de la transaction, nous décidons que mysql> LOCK TABLES trans READ, customer
nous ne voulons pas valider (peut-être nous WRITE;
sommes-nous aperçus que la balance d'Alice mysql> SELECT SUM(value) FROM trans WHERE
devenait négative), nous pouvons envoyer la customer_id=some_id;
commande ROLLBACK au lieu de COMMIT, et mysql> UPDATE customer SET
toutes nos mises à jour jusqu'à maintenant seront total_value=sum_from_previous_statement
annulées. -> WHERE customer_id=some_id;
mysql> UNLOCK TABLES;
3. Verrouillage en deux phases(Two Phase
Locking) Sans LOCK TABLES , Il est possible qu'un autre
thread ait inseré une nouvelle ligne dans la table
Le verrouillage en deux phases est une technique trans entre l'execution du SELECT et l'exécution
de prévention des conflits ( concurrences) basée de la requête UPDATE .
sur le verrouillage des objets en lecture ou
écriture avant d'effectuer une opération de 4. Mise en œuvre d'une transaction dans une
sélection ou de mise à jour. C'est alors une application
technique de contrôle des accès concurrents
consistant à verrouiller les objets au fur à mesure Une transaction est un ensemble d'instructions
des accès par une transaction (phase devant s'exécuter d'un seul bloc. C'est à dire que
d'acquisition de verrous: LOCK ) et à relâcher les les instructions sont soit toutes exécutées, soit
verrous seulement après obtention de tous les toutes annulées. Si une seule instruction du bloc
verrous (phase de relâchement : UNLOCK). échoue la transaction ne prends pas effet.
Sous Mysql , par exemple , il est possible de
verrouiller les tables dont vous aurez Par défaut, les Connection sont en mode auto-
besoin pour que les autres threads ne commit. C'est à dire que chaque instruction SQL
pourront pas intervenir sur ces tables est considérée comme une transaction. Vous
durant vos opérations, ni en extraire des pouvez changer ce comportement en utilisant la
informations si la table est en WRITE – méthode setAutoCommit(boolean).
locked si vous allez exécuter plusieurs
requêtes sur plusieurs tables par les Dans le cas ou l'auto-commit est desactivé, vous
commandes LOCK TABLES/UNLOCK devrez appeller la méthode commit pour
TABLES. effectivement valider la transaction. Pour annuler
Ces commandes peuvent être utilisées pour une transaction vous devez utiliser la méthode
verrouiller un type de table dans MySQL qui ne rollback. Cette méthode à pour effet d'annuler
supporte pas les transactions, et pour vous toutes les modifications faites par la transaction
assurez qu'aucun autre thread ne s'intercale entre courrante et de supprimmer les verrous en place.
un SELECT et un UPDATE .
a) Exemple d'une transaction en JAVA via
Syntaxe de LOCK TABLES/UNLOCK TABLES JDBC:

Si une erreur survient, une exception de type


SQLException est déclenchée. Dans ce cas, le
bloc catch annule la transaction. Sinon, elle est
confirmée. Dans tous les cas de figure (bloc
LOCK TABLES nom_de_table [AS alias] {READ | finally) on ferme la connexion à la base de
WRITE} données.
[, nom_de_table [AS alias] {READ | WRITE} ...]
2
ENI RV

Connection connection = null;


try{ Dim cnn1 As ADODB.Connection
connection = ...; Dim rstTitles As ADODB.Recordset
connection.setAutoCommit(false); Dim strCnn As String
//traitement des différentes instructions Dim strTitle As String
composant la transaction Dim strMessage As String
if(jeVeuxValider){
connection.commit();// c'est ici que l'on valide
la transaction ' Ouvrir la connexion.
connection.setAutoCommit(true); strCnn = "Provider=sqloledb;" & _
}else{ "Data Source=srv;Initial Catalog=Pubs;User
connection.rollback(); Id=sa;Password=; "
} Set cnn1 = New ADODB.Connection
} cnn1.Open strCnn
catch(SQLException sqle){
try{connection.rollback();} catch(Exception e){} ' Ouvrir la table Titles.
} Set rstTitles = New ADODB.Recordset
catch(Exception e){ rstTitles.CursorType = adOpenDynamic
try{connection.rollback();} catch(Exception e){} rstTitles.LockType = adLockPessimistic
} rstTitles.Open "titles", cnn1, , , adCmdTable
finally{
try{connection.close();} catch(Exception e){}
rstTitles.MoveFirst
}
cnn1.BeginTrans
b) Exemple de transaction en VB
' Parcourir le jeu d'enregistrements et
Méthodes BeginTrans, CommitTrans et demander à l'utilisateur s'il souhaite 'modifier le
RollbackTrans type d'un titre spécifié.

Ces méthodes gèrent le traitement des Do Until rstTitles.EOF


transactions dans un objet Connection, de la If Trim(rstTitles!Type) = "psychology" Then
manière suivante : strTitle = rstTitles!Title
• BeginTrans : lance une nouvelle strMessage = "Title: " & strTitle & vbCr & _
transaction. "Change type to self help?"
• CommitTrans : enregistre les
modifications et met fin à la transaction. ' Modifier le titre de l'employé spécifié.
Elle peut aussi commencer une nouvelle If MsgBox(strMessage, vbYesNo) = vbYes
transaction. Then
• RollbackTrans : annule les modifications
rstTitles!Type = "self_help"
effectuées lors de la transaction en cours rstTitles.Update
et met fin à cette dernière. Elle peut aussi End If
commencer une nouvelle transaction. End If
Exemple de méthodes BeginTrans,
CommitTrans et RollbackTrans (VB) rstTitles.MoveNext
Loop
Cet exemple change le titre de tous les livres de
psychologie figurant dans la table Titles de la
base de données. Une fois que la méthode
' Demander à l'utilisateur s'il veut valider toutes
BeginTrans a lancé une transaction qui identifie
les
toutes les modifications effectuées dans la table
' modifications apportées ci-dessus.
Titles, la méthode CommitTrans enregistre les
If MsgBox("Save all changes?", vbYesNo) =
modifications. Vous pouvez utiliser la méthode
vbYes Then
Rollback pour annuler les modifications que vous
cnn1.CommitTrans
avez enregistrées à l'aide de la méthode Update.
Else
cnn1.RollbackTrans
Public Sub BeginTransX()
3
ENI RV

End If myTrans.Rollback()
Response.Write(ep.ToString())
' Imprimer les données en cours dans le jeu Response.Write( "Neither record was written to
d'enregistrements. database." )
rstTitles.Requery Finally
rstTitles.MoveFirst myConnection.Close()
Do While Not rstTitles.EOF End Try
Debug.Print rstTitles!Title & " - " & rstTitles!
Type d)TRANSACTION EN PDO
rstTitles.MoveNext
Loop <?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1;
port=3306’’; 'dbuser'; 'dbpass';
' Restaurer les données originales, car il s'agit try {
d'une $dbh = new PDO($dsn, $user, $password);
' démonstration. $dbh->beginTransaction();
rstTitles.MoveFirst $dbh->exec("insert into staff
Do Until rstTitles.EOF (id, first, last) values (23, 'Joe', 'Bloggs')");
If Trim(rstTitles!Type) = "self_help" Then $dbh->exec("insert into salarychange
rstTitles!Type = "psychology" (id, amount, changedate)
rstTitles.Update values (23, 50000, NOW())");
End If $dbh->commit();
rstTitles.MoveNext
Loop }
catch (Exception $e)
rstTitles.Close { die('Erreur : ' . $e->getMessage());
cnn1.Close $dbh->rollBack();

End Sub }
catch (PDOException $e) {
c) Faire transaction Transact-SQL en utilisant echo 'Connexion échouée : ' . $e->getMessage();
DB SQL Server ASP.NET 2.0 et VB.NET }
?>
Tout d'abord, importer l'espace de noms
System.Data.SqlClient

Dim myConnection As New SqlConnection( "Data


Source=localhost;Initial
Catalog=Northwind;uid=sa;pwd=sa;" )
myConnection.Open()

Dim myTrans=myConnection.BeginTransaction()
Dim myCommand As New SqlCommand()
myCommand.Connection = myConnection
myCommand.Transaction = myTrans
Try
myCommand.CommandText = "Insert into Region
(RegionID, RegionDescription) VALUES (100,
'Description')"
myCommand.ExecuteNonQuery()
myCommand.CommandText = "delete * from
Region where RegionID=101"
myCommand.ExecuteNonQuery()
myTrans.Commit()
Response.Write( "Both records are written to
database." )
Catch ep As Exception
4

Vous aimerez peut-être aussi