7. TCL - Transaccions
7.1. Definició
Les transaccions són un concepte fonamental de tots els sistemes de base de dades. Una transacció és un conjunt de sentències INSERT, UPDATE i/o DELETE que constitueixen una operació única. És a dir: podrem fer que s'executen totes les sentències de la transacció o cap.
Les sentències entre el BEGIN i COMMIT es diuen bloc de transacció o transacció.
Nota
Les transaccions no funcionen en el motor MyISAM de MySQL. Cal usar InnoDB.
7.2. Sintaxi
Les sentències que volem que formen part d'una transacció han de començar amb el comandament BEGIN (o START TRANSACTION) i acabar amb COMMIT (per a que es facen efectives les sentències) o ROLLBACK (per a anul·lar les sentències de la transacció):
7.3. Utilitats
1) Si ocorre algun error durant la transacció, podem anul·lar la transacció i així cap dels passos no afectarà la base de dades (es desfan les accions realitzades).
2) Els estats entremitjos en una transacció sí que són visibles en eixa transacció però no en unes altres transaccions concurrents. És a dir, altres sessions no veuen cap canvi d'eixa transacció fins que no s'ha fet el COMMIT.
3) Problema de l'ou i la gallina (inserció en dos taules interdependents).
4) Podem desfer les accions fetes mentre no confirmem la transacció.
5) Podem desfer part de les accions mentre no confirmem la transacció (SAVEPOINT).
Exemple utilitat 1: prevenció d'errors inesperats
Pensem en una base de dades d'un banc que conté saldos dels comptes dels clients. Volem enregistrar un pagament de 100 € des del compte d'Alícia fins al compte de Pep:
| SQL | |
|---|---|
Este tipus d'operacions sol ser més complicat i implicar més sentències (introduir la transferència en un històric de moviments, etc). Però el que importa és que hi ha més d'una sentència d'actualització per a realitzar esta transferència bancària.
Els clients del nostre banc voldran que se'ls assegure que: o bé estes 2 actualitzacions es fan, o que cap d'elles es fa. No voldrien que el saldo es decrementara d'Alícia i no s'incrementara en Pep.
Necessitem una garantia que si hi ha algun error en alguna d'eixes operacions anteriors, que cap dels passos executats tinga efecte. Agrupar les actualitzacions en una transacció ens dóna esta garantia:
| SQL | |
|---|---|
Si després del 1r UPDATE es perdera la connexió amb la BD, no es faria el 2n UPDATE però tampoc el COMMIT. Això fa que els efectes del 1r UPDATE no es facen efectius realment en la base de dades.
Exemple utilitat 2: canvis entremitjos transparents a altres sessions
Una altra propietat important de bases de dades transaccionals està relacionada amb la idea d'actualitzacions atòmiques: quan les transaccions múltiples estan corrent concurrentment (és a dir: simultàniament, al mateix temps), cada una no deu veure els canvis incomplets fets per altres.
Per exemple, si una transacció està ocupada sumant tots els saldos dels comptes, no sumarà els saldos fins que no haja acabat la transacció que està fent el traspàs d'un compte a altre.
| SESSIÓ 1 | SESSIÓ 2 |
|---|---|
BEGIN; |
|
UPDATE comptes SET saldo = saldo - 100 WHERE nom = 'Alícia'; |
SELECT SUM(saldo) FROM comptes |
UPDATE comptes SET saldo = saldo + 100 WHERE nom = 'Pep'; |
|
COMMIT; |
Si la sessió 2 s'executa en el moment en què acaba el primer UPDATE, no veurà els efectes d'eixe UPDATE. Si no haguérem posat la sessió 1 dins d'una transacció, la sessió 2 s'hauria deixat 100 € per sumar, ja que haguera sumat el saldo d'Alícia sense els 100 i el saldo de Pep sense haver-li-ho sumat encara.
Exemple utilitat 3: problema de l'ou i la gallina
Suposem una base de dades d'una acadèmia d'informàtica, on hi ha tants alumnes com ordinadors. Cada alumne ha de tindre assignat un ordinador. I cada ordinador ha de tindre assignat un alumne:
Nota
Este disseny té redundància d'informació, però ens serveix per a l'exemple.
Per a introduir un ordinador deurà tindre assignat un alumne, però per a introduir un alumne deurà tindre assignat un ordinador.
Problema: el SGBD no ens deixarà inserir res (problema de l'ou i la gallina).
Solució: en la definició de les claus alienes, hem de posar la propietat DEFERRABLE, que farà que les comprovacions d'existència es realitzen en el moment en què acabe la transacció. Però! MySQL no admet el DEFERRABLE. Sí que és admès per SGBD com Oracle o PostgreSQL.
Quan inserim l'ordinador, no es comprova que existisca l'alumne 1001, ja que al ser la seua clau aliena de tipus DEFERRABLE, ho comprovarà en el moment del COMMIT. Igual passa en la inserció de l'alumne. Quan fem el COMMIT, es comprovaran les 2 coses i sí que es compliran.
Exemple utilitat 4: desfer canvis voluntàriament
Si durant l'execució de la transacció decidim que no volem acabar-la (potser ens adonem que el saldo d'Alícia es feia negatiu), podem executar l'ordre ROLLBACK en compte de COMMIT. Això farà que s'anul·le l'efecte de les actualitzacions de la transacció que estaven fetes:
| SQL | |
|---|---|
Exemple utilitat 5: desfer parcialment la transacció en curs
És possible controlar les accions en una transacció d'una manera més detallada. És a dir, en compte de descartar tota la transacció, podem descartar només part de la transacció.
Això es fa amb els SAVEPOINTS.
SAVEPOINTS
Els savepoints són "punts de salvament", que permeten descartar selectivament parts de la transacció (admetent la resta de la transacció).
Exemple:
Suposem que traspassem 100 € del compte d'Alícia al compte de Pep, però que, només haver-ho fet, ens adonem que volíem traspassar-ho al compte de Maria i no al de Pep. Si ens haguérem curat en salut utilitzant transaccions i savepoints, podríem desfer només unes sentències de la transacció i no tota:
Després d'haver definit un savepoint amb SAVEPOINT nom_del_savepoint, podré retrocedir, si cal, a eixe punt mitjançant l'ordre ROLLBACK TO nom_del_savepoint.
Les accions fetes en la transacció entre la definició del SAVEPOINT i el ROLLBACK TO corresponent es descarten, però es queden els canvis anteriors a la definició del SAVEPOINT.
Podem retrocedir a un savepoint sempre que volguem:
| SQL | |
|---|---|
Ara bé, si retrocedint a un savepoint en concret, s'esborraran automàticament tots els savepoints definits després d'eixe savepoint. Açò ho fa el sistema per a alliberar recursos.
| SQL | |
|---|---|
Savepoints: exemple 1
La següent transacció inserirà els clients 1000 i 1004:
| SQL | |
|---|---|
Savepoints: exemple 2
Què fa la següent transacció?
| SQL | |
|---|---|
Donarà error en el rollback to s2 perquè el rollback to s1 esborra el savepoint s2.
Nota
Encara que no treballem amb transaccions, MySQL tracta cada sentència SQL com si fóra una transacció d'una sola sentència:
És a dir, si per exemple s'està fent un UPDATE molt costós, mentre dura l'actualització, qualsevol altre intent d'actualització de la taula serà paralitzat fins que no acabe el primer UPDATE.
Exercicis sobre transaccions
-
Comprova que es poden desfer els canvis d'una transacció no acabada: a. Inicia una transacció. b. Fes diversos update/delete en algunes taules. c. Anul·la la transacció. d. Comprova que els canvis que has fet no han tingut efecte.
-
Comprova que mentre una transacció no acaba, una altra no pot vore els canvis fets: e. Inicia una transacció i fes algun canvi (update/delete) en una taula i comprova que, de moment, els canvis es poden veure. f. Obri en una altra sessió altra connexió a la mateixa bd. g. Comprova en esta 2a sessió que els canvis fets en la 1a sessió no es poden vore (ja que no està acabada la transacció). h. Ves a la 1a sessió i confirma la transacció. i. Ves a la 2a sessió i comprova que ara sí que estan els canvis fets.
-
Comprova que mentre una transacció no acaba, si havia fet una modificació en alguna taula, una altra sessió no pot fer cap modificació en eixa taula: j. Inicia una transacció i fes algun canvi (update/delete) en una taula i comprova que, de moment, els canvis es poden veure. k. Obri en una altra sessió altra connexió a la mateixa bd. l. Intenta fer un canvi (update/delete) en la mateixa taula. Voràs com el servidor deixa en espera eixa petició esperant que acabe la transacció de la primera sessió. m. Comprova que, quan acabe la transacció de la 1a sessió (tant si la confirmes com si l'acabes), l'update/delete de la 2a sessió acabarà d'immediat.
Nota
Depèn de la configuració, potser sí que deixe modificar un registre que no està sent modificat. Però no deixarà modificar el mateix registre que està sent modificat.
-
Comprova el funcionament dels savepoints: n. Inicia una transacció i fes algun canvi en una taula. o. Posa un savepoint. p. Fes algun altre canvi. q. Cancel·la la transacció només fins al savepoint. r. Confirma la transacció i comprova quin dels dos canvis ha quedat.
ANNEX: Còpies de seguretat
Fer una còpia de seguretat d'una Base de Dades és una feina d'administració obligatòria per mantenir la informació protegida. MySQL et permet realitzar esta senzilla tasca amb ordres des de la consola, una volta hem entrat en l'entorn textual de MySQL:
Exportar una base de dades
Sintaxi:
| SQL | |
|---|---|
Exemple:
| SQL | |
|---|---|
Importar una base de dades
Sintaxi:
| SQL | |
|---|---|
Exemple:
| SQL | |
|---|---|