DEXCELENCIA UNIVERSITARIA, FORTALEZA E MEXICO I Z U C A R D E M ATA M O R O S PROGRAMA ACADÉMICO DE TECNOLOGÍAS DE LA INFORMACIÓN actividad Transacciones en MySQL como requerimiento parcial para acreditar la asignatura de Base de Datos para Aplicaciones que presentan: Alumno Gemma Evelin Rodríguez Contreras Cristhian Mariscal Rangel Marco Antonio Sánchez Tambolan Isidro Daniel Meza Moreno No. Control TI102956 TI102951 TI102958 TI102905 Asesor Lic. Gonzalo Rosas Cabrera Izúcar de Matamoros, Pue., 21 de febrero de 2011
RESUMEN Una Base de Datos Transaccional alberga la idea de o todo ó mejor nada. Al ejecutar una transacción, el motor de base de datos nos garantizará la atomicidad, consistencia, aislamiento y durabilidad (ACID) de la transacción (o conjunto de comandos) que se utilice. Es importante aclarar que para trabajar con Transacciones, las tablas deben de ser de tipo InnoDB y no MyISAM, si son de este último tipo NO funcionará así que antes de continuar deben asegurarse que usarán una tabla InnoDB 1
1 DESARROLLO TRANSACCIONES Una transacción es una unidad lógica de procesamiento de la base que incluye una o más operaciones de acceso a la base de datos, que pueden ser de inserción, eliminación, modificación o recuperación. A continuación mencionaremos los tipos de entradas, denominadas registros de diario, que se escriben en el diario y la acción que realiza cada una de ellas. En estas entradas, T se refiere a un identificador de transacción único que el sistema genera automáticamente y que sirve para identificar cada transacción: Comandos: START TRANSACTION, COMMIT y ROLLBACK, Por defecto, MySQL se ejecuta con el modo autocommit activado. Esto significa que en cuanto ejecute un comando que actualice (modifique) una tabla, MySQL almacena la actualización en disco. Si se necesita desactivar el comando autocommit utilice el comando: SET AUTOCOMMIT=0; Debe usar COMMIT para almacenar los cambios en disco, cuándo se ejecuta es cuándo hasta ese momento todas las sentencias que le preceden tendrán efecto antes no. Ejecutando por ejemplo una sentencia UPDATE, esta sentencia no tenga ningún efecto hasta que nosotros lo indiquemos con COMMIT. Por ejemplo; UPDATE bd SET campo= valor WHERE id=1; 2
En cambio se utiliza ROLLBACK si se quiere ignorar los cambios hechos desde el comienzo de la transacción. Si realiza un comando ROLLBACK tras actualizar una tabla no transaccional dentro de una transacción, ocurre una advertencia. ER_WARNING_NOT_COMPLETE_ROLLBACK. Los cambios en tablas transaccionales se deshacen, pero no los cambios en tablas no transaccionales. Si quiere deshabilitar el modo autocommit para una serie única de comandos, puede usar el comando START TRANSACTION que indica que se ha iniciado la ejecución de la transacción: Ejemplo: START TRANSACTION; SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summary=@a WHERE type=1; COMMIT; 3
Ejemplos: Veremos un ejemplo completo, extraído del articulo fuente de esta publicación, donde utilizaremos START TRANSACTION (no es necesario AUTOCOMMIT en 0) CREATE TABLE `departamentos` ( `CODIGO` INTEGER(11) NOT NULL DEFAULT 0, `NOMBRE` VARCHAR(100), `PRESUPUESTO` INTEGER(11) DEFAULT NULL, PRIMARY KEY (`CODIGO`) )ENGINE=InnoDB Ahora, insertaremos registros de la tabla departamentos_externos a departamentos mediante una transacción: START TRANSACTION; SELECT @A := presupuesto FROM departamentos_externos WHERE codigo =11; INSERT INTO departamentos( codigo, nombre, presupuesto ) VALUES ( 11, Department test, @A ); COMMIT; En el ejemplo anterior se guardo el presupuesto del departamento externo 11 en la variable @A y luego fue asignado al presupuesto en la tabla departamentos. Otro ejemplo: START TRANSACTION; SELECT @A := presupuesto, @B := codigo, @C := nombre FROM departamentos_externos WHERE codigo=33; INSERT INTO departamentos( codigodep, nombredep, presupuesto ) VALUES (@B, @C, @A ); COMMIT ; 4
Otro ejemplo más: START TRANSACTION; SELECT @A:=PRESUPUESTO FROM departamentos_externos WHERE codigo=11; UPDATE departamentos SET PRESUPUESTO = PRESUPUESTO + @A WHERE codigo=33; COMMIT; Las actualizaciones a las tablas no-transaccionales se almacenan en el registro binario inmediatamente después de su ejecución. Para las tablas transaccionales como las tablas BDB o InnoDB, todas las actualizaciones (UPDATE, DELETE, o INSERT) que cambian alguna tabla son almacenadas en cache hasta que se recibe una sentencia COMMIT en el servidor. En ese momento mysqld escribe la transacción completa al registro binario antes de que se ejecute el COMMIT. Cuando el flujo de ejecución que gestiona la transacción comienza, reserva un buffer de tamaño binlog_cache_size para almacenar consultas. Si una sentencia es más grande de esto, el flujo abre un archivo temporal para almacenar la transacción. El archivo temporal se borra cuando acaba el flujo Sintaxis de SET TRANSACTION SET [GLOBAL SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE } Este comando prepara el nivel de aislamiento de transacción para la siguiente transacción, globalmente, o para la sesión actual. 5
El comportamiento por defecto de SET TRANSACTION es poner el nivel de aislammiento para la siguiente transacción (que no ha empezado todavía). Si usa la palabra clave GLOBAL el comando pone el nivel de aislamiento de transacción por defecto globalmente para todas las transacciones creadas desde ese momento. Las conexiones existentes no se ven afectadas. Necesita el permiso SUPER para hacerlo. Usar la palabra clave SESSION determina el nivel de transacción para todas las transacciones futuras realizadas en la conexión actual. En MySQL 5.0, InnoDB ofrece los cuatro niveles de aislamiento de transacciones descriptos por el estándar SQL. Se puede establecer el nivel predeterminado de aislamiento por todas las conexiones mediante el uso de la opción --transactionisolation en la línea de comandos o en ficheros de opciones. Por ejemplo, se puede establecer la opción en la sección [mysqld] de my.cnf de este modo: [mysqld] transaction-isolation = {READ-UNCOMMITTED READ-COMMITTED REPEATABLE-READ SERIALIZABLE} Un usuario puede cambiar el nivel de aislamiento de una sesión individual o de todas las nuevas conexiones con la sentencia SET TRANSACTION. Su sintaxis es la siguiente: SET [SESSION GLOBAL] TRANSACTION ISOLATION LEVEL 6
{READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE} Nótese que se usan guiones en los nombres de niveles de la opción --transactionisolation, pero no en la sentencia SET TRANSACTION. Los niveles de aislamiento de transacciones globales y de sesión pueden consultarse con estas sentencias: SELECT @@global.tx_isolation; SELECT @@tx_isolation; En el bloqueo a nivel de fila, InnoDB emplea bloqueo de clave siguiente (next-key). Esto significa que, además de registros de índice, InnoDB también puede bloquear el vacío que precede a un registro de índice para bloquear inserciones de otros usuarios inmediatamente antes del registro de índice. Un bloqueo de clave siguiente hace referencia a bloquear un registro de índice y la posición vacía antes de él. Bloquear una posición vacía es establecer un bloqueo que actúa solamente sobre el vacío anterior a un registro de índice. A continuación una descripción detallada de cada nivel de aislamiento en InnoDB: READ UNCOMMITTED Las sentencias SELECT son ejecutadas sin realizar bloqueos, pero podría usarse una versión anterior de un registro. Por lo tanto, las lecturas no son 7
consistentes al usar este nivel de aislamiento. Esto también se denomina lectura sucia (dirty read). En otro caso, este nivel de aislamiento funciona igual que READ COMMITTED. READ COMMITTED Similar en parte al mismo nivel de aislamiento de Oracle. Todas las sentencias SELECT... FOR UPDATE y SELECT... LOCK IN SHARE MODE bloquean solamente los registros de índice, no los espacios vacíos que los preceden, por lo tanto se permite la libre inserción de nuevos registros junto a los bloqueados. Las sentencias UPDATE and DELETE que empleen un índice único con una condición de búsqueda única bloquean solamente el registro de índice hallado, no el espacio que lo precede. En las sentencias UPDATE y DELETE que actúan sobre rangos de registros, InnoDB debe bloquear los espacios vacíos y bloquear las inserciones de otros usuarios en los espacios vacíos que hay dentro del rango. Esto es necesario debido a que las filas fantasma deben ser bloqueadas para que funcionen la replicación y recuperación en MySQL. Las lecturas consistentes se comportan como en Oracle: Cada lectura consistente, incluso dentro de la misma transacción, establece y lee su propia captura tomada de la base de datos. REPEATABLE READ Este es el nivel de aislamiento predeterminado de InnoDB. Las sentencias SELECT... FOR UPDATE, SELECT... LOCK IN SHARE MODE, UPDATE, y 8
DELETE que utilicen un índice único con una condición de búsqueda única, bloquean solamente el registro de índice hallado, no el espacio vacío que lo precede. Con otras condiciones de búsqueda, estas operaciones emplean bloqueo de clave siguiente (next-key), bloqueando el rango de índice cubierto por la operación incluyendo los espacios vacíos, y bloqueando las nuevas inserciones por parte de otros usuarios. En lecturas consistentes (consistent reads), hay una importante diferencia con respecto al nivel de aislamiento anterior: En este nivel, todas las lecturas consistentes dentro de la misma transacción leen de la captura de la base de datos tomada por la primera lectura. Esta práctica significa que si se emiten varias sentencias SELECT dentro de la misma transacción, éstas serán consistentes unas con otras. SERIALIZABLE Este nivel es similar a REPEATABLE READ, pero todas las sentencias SELECT son convertidas implícitamente a SELECT... LOCK IN SHARE MODE. 9
2 CONCLUSIONES Y RECOMENDACIONES Para concluir podemos decir que las transacciones son de mucha ayuda aunque son un tanto difíciles de comprender y de realizar, además hay que tomar en cuenta que al realizar una transacción en MySQL que apenas se realice un INSERT, UPDATE o DELETE se genera un bloqueo sobre la tabla y que otros clientes no pueden acceder a la tabla para escribir en esta. Otros clientes podrán realizar SELECT sobre la tabla, pero no podrán ver los datos del primer cliente hasta que los mismos sean confirmados. 10
3 REFERENCIAS Comandos Transaccionales y de Bloqueo de MySQL, el 21 de Febrero de 2011, de http://dev.mysql.com/doc/refman/5.0/es/commit.html Elmasrí R., & Navarethe, S. B. (2002). Fundamentos de sistemas de bases de datos (3a edición). México: Pearson. 11