Consistencia y Aislamiento en Transacciones de Bases de Datos

IV.7 Transacciones Consistentes

Como se acaba de leer, una transacción atómica es aquella en la que todas las acciones de la base de datos (b.d.) pueden ocurrir, o también ninguna. Una transacción durable es aquella para la que todos los cambios confirmados son permanentes. El SMBD no eliminará esos cambios, incluso en el caso de fracasar. Si la transacción es durable, el SMBD proporcionará las facilidades para recuperar los cambios de todas las acciones confirmadas cuando sea necesario.

Sin embargo, los términos consistentes y aislados no son tan definitivos como atómicos y durables. Considere la siguiente instrucción de actualización de SQL:

UPDATE CLIENTE

SET CódigodeÁrea = ‘425’

WHERE CódigoPostal = ‘98050’

Suponga que hay 500,000 tuplas en la tabla CLIENTE y que 500 tienen CódigoPostal igual a ‘98050’; le tomará algún tiempo al SMBD encontrar las 500 tuplas. Durante ese tiempo, ¿otras transacciones permitirán actualizar los campos de CódigodeÁrea o CódigoPostal de CLIENTE? Si la instrucción de SQL es consistente, estas actualizaciones estarán prohibidas. La actualización se aplicará para establecer que las tuplas como éstas existen en el momento en que el enunciado de SQL inició; esta consistencia se llama Consistencia del Nivel de Instrucción.


Ahora considere una transacción que contenga dos instrucciones de actualización de SQL:

BEGIN TRANSACTION

UPDATE CLIENTE

SET CódigoÁrea = ‘425’

WHERE CódigoPostal = ‘98050’

(Otra transacción en funcionamiento)

UPDATE CLIENTE

SET Descuento = 0.05

WHERE CódigoÁrea = ‘425’

(Otra transacción en funcionamiento)

COMMIT TRANSACTION

En este contexto, ¿qué significa consistente? La consistencia del nivel de instrucción quiere decir que cada instrucción procesa independientemente tuplas consistentes, pero que los cambios de otros usuarios de estos renglones se pueden permitir durante el intervalo entre las dos instrucciones SQL. El nivel de consistencia de la transacción significa que todas las tuplas impactadas por cualquiera de las instrucciones SQL son protegidas de cambios durante la transacción completa. Observe, sin embargo, que para algunas implementaciones de la consistencia del nivel de transacción, una transacción no verá sus propios cambios. En este ejemplo, la segunda instrucción SQL puede no ver los cambios en las tuplas derivadas de la primera instrucción SQL.


Nivel de Aislamiento de la Transacción

Los locks evitan que los procesos concurrentes ocasionen la pérdida de actualizaciones; pero hay otro tipo de problemas que no evitan. Específicamente, ocurre una lectura sucia cuando una transacción lee un registro cambiado que no ha sido registrado en la base de datos. Por ejemplo, esto puede ocurrir si una transacción lee un renglón cambiado por una segunda transacción no confirmada, la cual más tarde aborta.

Las lecturas no repetibles ocurren cuando una transacción relee datos que fueron leídos con anterioridad y encuentra modificaciones o eliminaciones ocasionadas por una transacción confirmada. Por último, las lecturas fantasmas tienen lugar cuando una transacción relee los datos y encuentra que se insertaron nuevos renglones como resultado de una transacción confirmada en la lectura anterior.

El estándar ANSI SQL de 1992 define cuatro niveles de aislamiento, que especifican cuál de estos problemas se permite que ocurra. El objetivo es que el programador de la aplicación pueda declarar el tipo de nivel de aislamiento que quiere y entonces tener la administración de los locks del SMBD, así como lograr ese nivel de aislamiento.

Como se muestra en la figura (no incluida), la lectura en un nivel de aislamiento no confirmado permite que ocurran lecturas sucias, lecturas no repetibles y lecturas fantasmas. Con aislamiento de lecturas confirmadas, las lecturas sucias están prohibidas. El nivel de aislamiento de lecturas repetibles prohíbe tanto las lecturas sucias como las no repetibles.


IV.9 Planes y Recuperabilidad

Cuando varias transacciones se ejecutan de manera concurrente e intercalada, el orden de ejecución de sus operaciones constituye lo que se conoce como plan (o historia) de las transacciones.

Planes (historias) de transacciones

Un plan (o historia) P de n transacciones T1, T2,…, Tn es un ordenamiento para las operaciones de las transacciones sujeto a la restricción de que, para cada transacción Ti que participe en P, las operaciones de Ti en P deben aparecer en el mismo orden en que ocurren en Ti.

Para fines de recuperación y control de concurrencia, nos interesan principalmente las operaciones leer_elemento y escribir_elemento de las transacciones, así como las operaciones de confirmar y abortar.

Una notación abreviada para escribir un plan emplea los siguientes símbolos:

  • Leer_elemento (l)
  • Escribir_elemento (e)
  • Confirmar (c)
  • Abortar (a)

A esta notación se le añade como subíndice el identificador de la transacción (número de la transacción) a cada operación del Plan. En esta notación, el elemento de la b.d. que se lee o escribe, X, sigue a las operaciones l y e entre paréntesis.


Problema de pérdidas en la actualización

El procesamiento concurrente del ejemplo anterior no tiene problemas porque dos usuarios están procesando datos diferentes. Pero supongamos que ambos quieren procesar el artículo 100.

El usuario A lee el registro del artículo 100 en el área de trabajo de un usuario. De acuerdo con el registro, existen 10 unidades en inventario. El usuario B lee el registro del artículo 100 en otra área de trabajo. Nuevamente, de acuerdo con el registro existen 10 unidades en inventario. Ahora el usuario A toma cinco, disminuye la cantidad de elementos en su área de trabajo a cinco y rescribe el registro para el artículo 100. Luego el usuario B toma tres, disminuye la cantidad en su área de trabajo a siete, y rescribe el registro para el elemento 100. La b.d. ahora muestra, incorrectamente, que existen siete elementos en el inventario del elemento 100.


Terminología de locks

Los locks se pueden poner ya sea en forma automática, a través del SMBD, o mediante una instrucción enviada al SMBD desde el programa de aplicación, o a solicitud del usuario.

Los locks que impone el SMBD se llaman locks implícitos; los que se ponen mediante una instrucción se llaman locks explícitos.

En el ejemplo anterior los locks se aplicaron en los renglones de datos.

Algunos SMBD aplican locks por página, por tabla, o a toda la b.d.; al tamaño de un lock se le llama granularidad del bloqueo.

Los locks también varían en su tipo. Un lock exclusivo impide el acceso a cualquier tipo de artículo. Ninguna otra transacción puede leer o cambiar los datos. Un lock compartido impide que se hagan cambios al elemento de datos, pero permite la lectura. Es decir, otras transacciones pueden leer de ese dato siempre y cuando no intenten modificarlo.


IV.13 Bloqueo Optimista / Bloqueo Pesimista

Existen dos estilos básicos de Bloqueos: Optimista y Pesimista.

Con el optimista se supone que no ocurrirá ningún conflicto. Los datos se leen, se procesan las transacciones y las actualizaciones y después se realiza una verificación para ver si ocurre algún conflicto; en caso contrario se termina la transacción. Si hay un conflicto ésta se repite hasta que se procese sin ningún conflicto; como se muestra a continuación:

SELECT PRODUCTO.Nombre, PRODUCTO.Cantidad
FROM  PRODUCTO
WHERE PRODUCTO.Nombre=’Lápiz’
ViejaCantidad=PRODUCTO.Cantidad
SET NuevaCantidad=PRODUCTO.Cantidad – 5
{procesar transacción – llevar a cabo acción de excepción si 
NuevaCantidad<0, etc., suponer que todo está bien}
LOCK PRODUCTO
UPDATE PRODUCTO
SET PRODUCTO.Cantidad=NuevaCantidad
WHERE PRODUCTO.Nombre=’Lápiz’
  AND PRODUCTO.Cantidad=ViejaCantidad
UNLOCK PRODUCTO
{comprobar para ver si la actualización tuvo éxito; de lo contrario, 
repetir la transacción}

En esta secuencia se muestra un lock optimista; primero se leen los datos y se almacena el valor real de Cantidad de lápices en la variable ViejaCantidad; después la transacción se procesa y, suponiendo que todo está bien, se aplica un lock en PRODUCTO; se emite una instrucción SQL para actualizar el renglón lápiz con una condición WHERE con lo cual el valor actual de Cantidad sea igual a ViejaCantidad. Si otra transacción no ha cambiado la Cantidad del renglón lápiz, entonces UPDATE (actualización) tendrá éxito. Si otra transacción ha cambiado la Cantidad del renglón lápiz, UPDATE fallará y será necesario repetir la transacción.

El pesimista supone que ocurrirá el conflicto. Primero se aplican los locks, después se procesa la transacción y luego se liberan los locks; como se muestra a continuación:

LOCK PRODUCTO
SELECT PRODUCTO.Nombre, PRODUCTO.Cantidad
FROM PRODUCTO
WHERE PRODUCTO.Nombre=’Lápiz’
SET NuevaCantidad=PRODUCTO.Cantidad – 5
{procesar transacción – llevar a cabo acción de excepción si 
NuevaCantidad<0, etc., suponer que todo está bien}
UPDATE PRODUCTO
SET PRODUCTO.Cantidad=NuevaCantidad
WHERE PRODUCTO.Nombre=’Lápiz’
UNLOCK PRODUCTO
{no se necesita comprobar si la actualización tuvo éxito}

La ventaja del lock optimista es que se obtiene sólo después de que la transacción ha sido procesada. Así, el lock se mantiene durante menos tiempo que con el lock pesimista. Si la transacción es complicada, o si el cliente es lento, el lock se mantendrá durante un tiempo considerablemente menor. Esta ventaja será aún más importante si la granularidad del lock es grande; por ejemplo la tabla PRODUCTO.

La desventaja del lock optimista es que si existe mucha actividad en el renglón lápiz (por ejemplo), la transacción se puede repetir muchas veces. Así, las transacciones que implican mucha actividad en un renglón determinado son muy poco adecuadas para el lock optimista.

Declarar las Características del Lock

Las decisiones acerca de los tipos y estrategias de los locks se han tenido que tomar a base de pruebas y errores; por tal, los programas de aplicación de base de datos, por lo general, no emiten locks explícitos, sino que marcan las fronteras de la transacción y después establecen el tipo de comportamiento de bloqueo que desean use el SMBD. De esta manera, si se necesita cambiar el comportamiento del bloqueo, no se necesita rescribir la aplicación para colocar locks en diferentes lugares en la transacción. En lugar de eso, se cambia la declaración del lock.

A continuación se muestra la transacción de lápiz con las fronteras de la transacción marcadas con BEGIN TRANSACTION, COMMIT TRANSACTION y ROLLBACK TRANSACTION. Estas fronteras son la información esencial que el SMBD necesita para aplicar las diferentes estrategias de bloqueo. Si el programador declara que quiere que el lock sea optimista, el SMBD establecerá implícitamente los locks en los lugares correctos para ese tipo de bloqueo; si más tarde el programador cambia las tácticas y solicita el bloqueo pesimista, el SMBD configurará implícitamente los locks en un lugar diferente.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.