TRANSACCIONES EN MYSQL
Las transacciones son un conjunto de consultas que se ejecutan como si fuesen una. Y por
esto, permiten asegurar la consistencia de los datos, ya que si en mitad del proceso una
consulta falla, todos los cambios producidos por consultas anteriores pueden ser revertidos.
Hay situaciones en las que se hace necesario realizar ms de una consulta al mismo tiempo,
y todas tienen que ser correctas para que los datos sean consistentes y tengan sentido, de otro
modo se tendra informacin "colgada" y desvinculada. En el mejor de los casos esta
informacin provocara un desperdicio de espacio en la base de datos, pero lo ms probable
es que adems lleve a errores a la hora de mostrarse y de hacer clculos con ella.
Parte de este problema se resuelve teniendo una buena estructura de base de datos, con claves
forneas relacionando los campos correspondientes.
Pero para mayor seguridad, es bueno usar lo que en jerga de base de datos lo que se conoce
como transacciones.
Las transacciones sirven para asegurar la consistencia de la informacin, asegurando que un
conjunto de sentencias se ejecuten correctamente, o no se ejecuten.
EJEMPLO
Un sitio web bancario tiene 2 usuarios, ambos trabajando sobre la misma cuenta.
El usuario 1 pide incrementar su saldo en 10, mientras que el usuario 2 pide disminuirlo (a
travs de un formulario, por ejemplo)
El programador del sistema no puede decidir el orden en el que se ejecutarn las consultas
(Integridad Referencial), as que bien podra suceder lo siguiente:
bal1:=... SELECT balance FROM cuentas WHERE cuenta=X -- usuario 1
bal2:=... SELECT balance FROM cuentas WHERE cuenta=X -- usuario 2
En este punto, existen dos copias de la aplicacin que contienen una variable $balance cada
una. Se puede suponer que ambas necesitan actualizar el valor en la base de datos:
UPDATE cuentas SET balance= (bal1+10) WHERE cuenta=X -- usuario 1
UPDATE cuentas SET balance= (bal2-10) WHERE cuenta=X -- usuario 2
El resultado es que ambas copias del programa ejecutaron sus consultas con la informacin
de balance que tenan, por lo que el resultado final es como si la consulta del usuario 1 no se
hubiera ejecutado nunca, ya que el usuario 2 actualiza el registro con informacin vieja. Al
final, en vez de quedar con el mismo saldo, la cuenta termina perdiendo 10.
Lo que se necesita para este conjunto de consultas, es lo que se denomina ACID, un acrnimo
ingls que quiere decir Atomicidad, Consistencia, Aislamiento y Durabilidad.
CMO USAR TRANSACCIONES?
Usar transacciones es muy simple: antes de ejecutar la primer consulta, se ejecuta una que
solamente contiene BEGIN. Luego se ejecutan las consultas que deban ejecutarse. Si stas
resultan exitosas, se termina la transaccin con COMMIT, lo cual provoca que los cambios
hechos por las consultas anteriores sean permanentes. Si las consultas fallan en algn paso,
se puede volver al estado anterior al comienzo de la transaccin ejecutando ROLLBACK
Aunque los datos no sean realmente escritos a la o las tablas involucradas hasta ejecutar el
COMMIT, las consultas devuelven lo mismo que si lo fueran, es decir, para saber si una
consulta fall basta con ver el valor de retorno de mysql_query y para ver el nmero de filas
afectadas sigue valiendo usar mysql_num_rows
Mientras la transaccin est ejecutndose, los datos (en el caso de InnoDB las filas y en el
caso de MyISAM las tablas) afectados quedan bloqueados, nadie puede acceder a ellos.
Cualquier consulta que tenga que ver con los mismos datos ser demorada hasta que la
transaccin termine. Esto implica que usar transacciones es un poco ms lento que no usarlas,
pero a la vez implica que los datos involucrados no pueden ser modificados por otra copia de
la aplicacin, y por lo tanto se evita la situacin planteada al principio como ejemplo.
Dicha situacin, implementada de forma "transaccional" en PHP, quedara:
1 <?php
2 mysql_query("BEGIN");
3 $balance = ..... mysql_query("SELECT balance FROM cuentas WHERE
cuenta=X");
4 $resultado = mysql_query("UPDATE cuentas SET balance=$balance+10 WHERE
cuenta=X");
6 if ($resultado !== false)
7 // la consulta fue exitosa
8 mysql_query("COMMIT");
9 else
10 mysql_query("ROLLBACK");
AUTOCOMMIT
MySQL tiene una variable de entorno llamada autocommit, que por defecto tiene el valor 1.
Configurado de esta manera no se pueden usar transacciones, porque MySQL
automticamente hace un COMMIT luego de cada consulta.
Para usar transacciones entonces, hay que poner autocommit a 0 (desactivarlo).
Nota: si autocommit se pone a cualquier nmero N > 1, MySQL hace un COMMIT
automtico luego de N consultas.
Para cambiar el valor de autocommit, simplemente se usa:
SET autocommit = 0;