lunes, 1 de julio de 2013

Extensión MySQLi - Parte 4: Transacciones

Las transacciones con la extensión MySqli son un mecanismo que nos asegura que todas y cada de las consultas que las forman van a ser ejecutadas. En el caso de que falle alguna declaración, la transacción no se llevará a cabo.

Pero tenemos que tener cuidado con el tipo de tabla o tablas sobre las que vamos a realizar la transacción. Como sabemos los tipos más comunes de motores de almacenamiento de tablas en MySQL son MyISAM y InnoDB. Siendo el primero el que se utiliza por defecto si no se dice nada y que excluye la seguridad proporcionada por la integridad referencial. Sin embargo con este tipo no se permiten transacciones. Así que transacciones solo se pueden llevar a cabo sobre tablas InnoDB.

Fases de las transacciones

1. Iniciar transacción - Autocommit

Por defecto, MySQL se ejecuta en modo autocommit. Tener activo el modo de ejecución automática (autocommit) significa que cada consulta se tratará como una transacción individual.  Lo que  conlleva a  que tan pronto como se ejecuta una sentencia se modifica una tabla de MySQL. Haciendo imposible la vuelta atrás (modificación permanente). Pero gracias a InnoDB y a las transacción, las consultas se puede revertir (roll back). Y para ello tenemos que desactivar el citado modo de ejecución automática. Lo que iniciará la transacción.

A) Interfaz orientada a objetos

 bool mysqli::autocommit ( bool $mode )  

 $mysqli = new mysqli("localhost", "my_user", "my_password", "demo");  
 if($mysqli->connect_errno) die($mysqli_connect_error)  
 $mysqli->autocommit(false);  

B) Interfaz procedimental

 bool mysqli_autocommit ( mysqli $link , bool $mode )  

 $con = mysqli_connect("localhost", "my_user", "my_password", "demo");  
 if (mysqi_connect_errno()) die(mysqli_connect_error())  
 mysqli_autocommit($con, false);  

2. Consultas

A) Interfaz orientada a objetos

 $result = $mysqli->query($sql1);  
 if ($mysqli->errno) {  
     $flag = false;  
     echo "Error: " . $mysqli->error . ". ";  
 }  
 $result = $mysqli->query($sql2);  
 if ($mysqli->errno) {  
     $flag = false;  
     echo "Error: " . $mysqli->error . ". ";  
 }  


B) Interfaz procedimental

 $flag = true;  
 $sql1 = "INSERT INTO usuario ('nombre','email') VALUES ('jose','prueba1@ejemplo.com')";  
 $sql2 = "INSERT INTO usuario ('nombre','email') VALUES ('juan','prueba2@ejemplo.com')";  
 $result = mysqli_query($con, $sql1);  
 if (mysqli_errno($con)) {  
     $flag = false;  
     echo "Error: " . mysqli_error($con) . ". ";  
 }  
 $result = mysqli_query($con, $sql2);  
 if (!mysqli_errno($con)) {  
     $flag = false;  
     echo "Error: " . mysqli_error($con) . ". ";  
 }  

3. Finalizar o revertir transacción

Como se ha comentado, lo importante de una transacción es que el desarrollador tiene el control de cuando hacer efectiva la modificación permanente o revertir estas modificaciones ocasionadas por las consultas.

A) Interfaz orientada a objetos

Con la primera de las siguientes funciones procederemos a hacer el commit en la base de datos. Esto quiere decir que las modificaciones serán permanentes.
Con la segunda opción revertimos la transacción actual y por lo tanto ninguna de las modificaciones de las consultas se hacen efectivas.

 bool mysqli::commit ( void )  
 bool mysqli::rollback ( void )  

 if ($flag) {//si no ha habido error en las consultas  
     $mysqli->commit();  
     echo "Consultas ejecutadas correctamente";  
 } else {  
     $mysqli->rollback();  
     echo "Todas las consultas han sido revertidas";  
 }  

B) Interfaz procedimental

 bool mysqli_commit ( mysqli $link )  
 bool mysqli_rollback ( mysqli $link )  

 if ($flag) {//si no ha habido error en las consultas  
     mysqli_commit($con);  
     echo "Consultas ejecutadas correctamente";  
 } else {  
     mysqli_rollback($con);  
     echo "Todas las consultas han sido revertidas";  
 }  

Es muy importante saber que tanto si se confirma una transacción o se revierte, devolveremos la conexión de base de datos a modalidad autocommit hasta que la siguiente llamada que inicia una nueva transacción.

Y también hay que tener cuidado con rollback() ya que no todas las sentencias sql pueden ser revertidas dentro de una transacción. Ya que hay un número determinado de sentencias que llevan un commit implícito:


  • CREATE DATABASE
  • ALTER DATABASE
  • DROP DATABASE
  • CREATE TABLE
  • ALTER TABLE
  • DROP TABLE
  • RENAME TABLE
  • TRUNCATE TABLE
  • CREATE INDEX
  • DROP INDEX
  • CREATE EVENT
  • DROP EVENT
  • CREATE FUNCTION
  • DROP FUNCTION
  • CREATE PROCEDURE
  • DROP PROCEDURE

Entradas relacionadas

Extensión MySQLi - Parte 1: Consultas de modificación
Extensión MySQLi - Parte 2: Consultas de selección
Extensión MySQLi - Parte 3: Consultas preparadas y escapado

1 comentario:

  1. Buenas, mi duda es la siguiente. Cómo puedo almacenar los datos, que obtengo de una consulta y guardarlos en variables, para luego mostrarlos u operar con ellos mas adelante.

    Hasta ahora vengo así:

    connect_errno > 0){
    die('Imposible conectarse con la base de datos: [' . $db->connect_error . ']');
    }

    $nom=""; // Inicializo la variable
    $nom = $_REQUEST['nombre']; //nombre es un campo de formulario
    $bot = $_REQUEST['boton']; //boton es el boton enviar del formulario

    $sql = <<query($sql)){
    die('Ocurrió un error: [' . $db->error . ']');
    }




    while($fila = $resultado->fetch_assoc()){
    echo $fila['usuario'] . '
    '; //muestra el usuario "todo OK"
    $mostrausu = $fila['usuario']; //aqui ya hice algo erróneo
    $mostradni = $fila['dni'];
    }




    ?>


    POR FAVOR, AYUDA!

    ResponderEliminar