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:
COMMIT
n'a pas encore été exécutée au sein de la
transaction t2 .
Cela pose problème si une commande ROLLBACK
est émise au sein de t2.
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 |
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.
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
.