El control de transacciones (TCL)
La problemática de los accesos concurrentes
En la mayoría de desarrollos informáticos se plantea el problema de los accesos simultáneos a ciertos datos por parte de usuarios diferentes.
De hecho, un programador de aplicaciones debe prever la gestión de los accesos concurrentes utilizando las herramientas que proporciona la base de datos.
La mayoría de los SGBDR permiten bloquear datos antes de la actualización para impedir a otros usuarios modificar el mismo dato antes que el primero haya confirmado la modificación.
1. Ilustración de accesos concurrentes
a. Ejemplo 1: actualizaciones simultáneas
Volvamos a la tabla Tarifas:
SELECT * FROM Tarifas;
idTarifa |
Hotel |
tipoHabitacion |
FechaInicio |
FechaFin |
Precio |
1 |
1 |
1 |
2024-10-01 |
2025-04-14 |
49,99 |
2 |
1 |
2 |
2024-10-01 |
2025-04-14 |
59,99 |
3 |
1 |
3 |
2024-10-01 |
2025-04-14 |
68,99 |
4 |
1 |
4 |
2024-10-01 |
2025-04-14 |
59,99 |
5 |
1 |
5 |
2024-10-01 |
2025-04-14 |
69,99 |
Ahora un usuario lee el registro número 2 y LUEGO realiza una modificación de la tabla sumando 10 € al precio del tipo de habitación número 2 del hotel número 1.
En el mismo momento otro usuario también suma 15 € a este registro número 2.
USUARIO 1 |
Valor PRECIO |
USUARIO 2 |
Valor PRECIO |
LECTURA Tarifas NUMERO 2 |
59,99 |
||
ACTUALIZACIÓN PRECIO = PRECIO + 10 |
69,99 |
LECTURA Tarifas NUMERO 2 |
59,99 |
ACTUALIZACIÓN PRECIO= PRECIO + 15 |
74,99 |
||
GRABACIÓN REGISTRO NUMERO 2 |
69,99 |
||
GRABACIÓN REGISTRO NUMERO 2 |
74,99 |
Como resultado de este pequeño escenario, el valor final del precio de la habitación será de 74,99 €. Tendría que ser de 84,99 €. De hecho, si las dos transacciones se hubieran realizado una después de la otra, el resultado hubiera sido:
59,99 + 10 = 69,99 y después 69,99 + 15 = 84,99 €
Por tanto, el usuario 1 piensa que ha sumado 10 € al precio y el segundo usuario realmente ha sumado los 15 € al precio.
El usuario 2 no ha tenido en cuenta la modificación del primer usuario que pone el precio a 69,99. La suma de los 15 € se debería aplicar a 69,99 y no a 59,99.
b. Ejemplo 2: incoherencia de los datos después de una modificación de otro usuario
Un usuario lee la tabla Tarifas al inicio de su programa, y a continuación realiza acciones respecto a lo que ha recuperado....
Concepto de transacción
Para limitar los problemas indicados en los párrafos anteriores, el programador se debe preguntar: ¿cuáles son los objetos (fila, columna, tabla…) que manipulo en mi proceso y cómo evitar que otro usuario no pueda bloquearlos antes que yo haya terminado mis actualizaciones?
En este momento, comenzamos a hablar de transacción.
1. Definición de una transacción
La transacción permite limitar el inicio y el final de una acción en la base de datos, sobre una o más tablas, que deben quedar coherentes.
La transacción es un concepto que proviene de las aplicaciones llamadas «transaccionales». Cada vez que hay intercambio de datos entre la aplicación y el usuario, se habla de aplicación transaccional.
Todas las aplicaciones utilizan mecanismos de bloqueo.
2. Cómo evitar las incoherencias de datos
Existen varios métodos para garantizar la coherencia de la base de datos:
-
Ejecutar las transacciones unas después de las otras (en serie). El inconveniente principal es el tiempo de espera para los usuarios. Esto equivale a tener una aplicación monousuario.
-
Posibilidad de bloquear al principio del programa principal todos los objetos implícitamente y liberarlos al final. Este método corre el riesgo de bloquear al resto de usuarios mucho tiempo si el usuario no valida rápidamente la pantalla y, por ejemplo, se va a una reunión.
-
Sin bloqueo de registros al principio, pero con lectura de los datos y guardado en memoria del contenido para volver a leerlos justo antes de la actualización, para asegurar que los datos no se han modificado en ese lapso de tiempo. Si los valores guardados son diferentes de los valores que se han vuelto a leer, habría que cancelar la transacción y mostrar un mensaje al usuario para indicar el problema y decirle que debe volver a introducir los datos.
3. Implementación de un bloqueo
Según la norma SQL-92, se puede indicar a la base de datos qué tipo de método se quiere utilizar.
Para activar cualquier modo de bloqueo, hay que utilizar el comando: SET TRANSACTION ISOLATION LEVEL.
Existen cuatro modos de bloqueo.
El modo por defecto en MySQL es el modo REPEATABLE-READ. En Oracle, PostgreSQL y SQL Server, es el modo READ COMMITTED.
Generalmente la acción se aplica a una sesión...
Ejercicio
-
Crear una transacción que vacíe la tabla PELICULA.
-
Luego contar el número de actrices Carrie Fisher.
-
Insertar en la tabla PELICULA la película Subway, géneros POLICÍACA y DRAMA, estrenada el 10 de abril de 1985 en Francia, por el REALIZADOR Luc Besson, distribuida por GAUMONT con esta sinopsis: "Cuenta las aventuras de la población subterránea en los túneles del metro de París" .
-
Crear un punto de sincronización.
-
Insertar en la tabla PELICULA la película Nikita, géneros DRAMA y ROMÁNTICA, estrenada el 21 de febrero de 1990 en Francia, por el REALIZADOR Luc Besson, distribuida por GAUMONT con esta sinopsis: “Nikita, condenada a cadena perpetua, es obligada a trabajar en secreto para el gobierno como agente muy cualificada de los servicios secretos”.
-
Eliminar a la actriz Carrie Fisher.
-
Seleccionar las películas del REALIZADOR Luc Besson estrenadas entre el 1 de enero de 1985 y el 30 de mayo de 1985, ordenadas por título de película.
-
Colocar un segundo punto de sincronización.
-
Insertar en la tabla PELICULA la película Subway, géneros POLICÍACA y DRAMA, estrenada el 10 de abril de 1985 en Francia, por el REALIZADOR Luc Besson, distribuida por GAUMONT con esta sinopsis: "Cuenta las aventuras de la población subterránea en los túneles del metro de París".
-
Cancelar...
Solución del ejercicio
Sintaxis Oracle
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
/* Vaciado de la tabla PELICULA */
DELETE FROM PELICULA;
SELECT COUNT(*) FROM ACTOR WHERE APELLIDO = 'FISHER' AND NOMBRE =
'CARRIE';
INSERT INTO PELICULA VALUES (1,'SUBWAY','POLICIACA','DRAMA',
TO_DATE('10/04/1985','DD/MM/YYYY'),1,'GAUMONT',
'Cuenta las aventuras de la población subterránea en los túneles del metro
de París.');
/* Posicionamiento del primer punto */
SAVEPOINT ETAPA_NUMERO1;
INSERT INTO PELICULA VALUES (2,'NIKITA','DRAMA','ROMANTICO',
TO_DATE('21/02/1990','DD/MM/YYYY'),1,1,'GAUMONT',
‘Nikita, condenada a cadena perpetua, es obligada a trabajar en secreto
para el gobierno como agente muy cualificada de los servicios secretos.');
DELETE FROM ACTOR WHERE APELLIDO = 'FISHER' AND NOMBRE = 'CARRIE';
SELECT T1 * FROM PELICULA T1 INNER JOIN REALIZADOR ON T1.IDENT_REALIZADOR
=REALIZADOR.IDENT_REALIZADOR WHERE NOMBRE = 'LUC' AND FECHA-ESTRENO
BETWEEN ('01/01/85') AND ('30/05/1995')
ORDER BY TITULO;
/* Posicionamiento del segundo punto */
SAVEPOINT ETAPA_NUMERO2;
INSERT INTO PELICULA VALUES (3,'SUBWAY','POLICIACA','DRAMA',
TO_DATE('10/04/1985','DD/MM/YYYY'),1,1,'GAUMONT',
' Cuenta las aventuras de la población subterránea en los túneles del metro
de París'); ...