ULg


Travaux Pratiques du Cours de Bases de Données




Les transactions avec SQL/MySQL

SQL

Dans SQL, on spécifie le début d'une transaction avec la commande BEGIN WORK et on indique la fin par un COMMIT ou ROLLBACK . Toutefois, en ANSI-SQL (le standard), les transactions sont implicites: tous les déclarations entre deux COMMIT ou ROLLBACK forment une transactions. De plus, SQL prévoit plusieurs "niveaux d'isolation" au niveau d'une transaction, "READ UNCOMMITTED", "READ COMMITTED", "REPEATABLE READ" et "SERIALIZABLE". Le niveau peut être changé via la commande SET TRANSACTION ISOLATION LEVEL niveau Dans tous les cas, lorsqu'on procède à une écriture (via la commande UPDATE par exemple, on respecte la règle des deux phases, à savoir qu'un verrou en écriture est placé sur les données modifiées. Les différences interviennent lors des lectures, via une commande SELECT . Avec les différents niveaux d'isolation, des anomalies peuvent survenir:

Le tableau ci-après associe les anomalies possibles aux 4 niveaux d'isolation:

Isolation Level
Dirty Read
Non-repeatable Read
Phantoms
READ UNCOMMITTED possible possible possible
READ COMMITTED jamais possible possible
REPEATABLE READ jamais jamais possible
SERIALIZABLE jamais jamais jamais
Enfin, on peut égalemnt placer des verrous en lecture/ecriture sur des tables entières via la commande LOCK TABLES t1 { WRITE | READ } ... et libérer les verrous via la commande UNLOCK TABLES . L'utilité de ces commandes est de simuler des transaction manuellement ou bien de diminuer le temps d'execution de requetes.

MySQL

Deux types de tables sont dits transactionnel, c-à-d supporte les transactions suivant le paradigme ACID, InnoDB et BDB.

Par defaut, les requetes individuelles correspondent à des transactions (valeur de la variable AUTOCOMMIT = 1). Ce qui veut dire que dès qu'une commande est executée, un COMMIT implicite est émis. Pour changer cela, il y a deux possibilités. Soit mettre la variable AUTOCOMMIT à 0 ( SET AUTOCOMMIT = 0) et executer des COMMIT/ROLLBACK explicites pour délimiter les transactions, soit utiliser les commande BEGIN WORK ... COMMIT/ROLLBACK .

Au sein des tables InnoDB, l'exclusion se fait à l'aide de verrous placés sur les lignes (plus spécifiquement sur les valeurs des index).

Suivant la version du serveur MySQL, certains niveaux d'isolation sont possibles. Avec la version courante sur ms800, seule le niveau "READ COMMITTED" semble accessible. Par contre, sur la version sur fantasio.montefiore.ulg.ac.be permet tous les niveaux.

Afin d'éviter les problèmes mentionnés plus haut au sein d'un niveau d'isolation autre que "SERALIZABLE", on peut utiliser une déclaration plus ou moins explicite de demande de verrous. Ainsi, une commande de lecture SELECT ... LOCK IN SHARE MODE a pour effet de placer un verrou en lecture sur toutes les données lues, ce qui garantit qu'aucune autre transaction ne modifiera les données concernées ce qui élimine les "dirty reads" et les "non-repeatable read". Une commande en lecture SELECT ... FOR UPDATE place quant à elle un verrou en écriture sur les données. Les verrous sont automatiquement relaches a la fin de la transaction.

Remarque : On peut éviter l'utilisation de transaction dans certains cas en procédant à une mise à jour "relative", du type UPDATE ... set attribut = attribut + C .


latour@montefiore.ulg.ac.be