Bases de Datos II Unidad III BASES DE DATOS II UNIDAD III III.-PROBLEMAS DE CONCURRENCIA. Los temas de la concurrencia y la recuperación van de la mano y ambos son parte del tema más general de la administración de transacciones. Por lo general el término de la concurrencia se refiere al hecho de que los DBMS’s (Sistemas de Administración de Datos) permiten que muchas transacciones accedan a una misma base de datos a la vez. Como bien es sabido, en un sistema de éstos se necesita algún tipo de mecanismo de control de concurrencia para asegurar que las transacciones concurrentes no interfieran entre sí. 3.1.-PROBLEMAS DE CONCURRENCIA. Comencemos considerando alguno de los problemas que debe resolver cualquier mecanismo de control de concurrencia. Existen esencialmente tres maneras en las que las cosas pueden salir mal; esto es, tres formas en las que una transacción, aunque sea correcta por sí misma, puede producir una respuesta incorrecta si alguna otra transacción interfiere también puede ser correcta por sí misma; lo que produce el resultado incorrecto general es el intercalado sin control entre las operaciones de las dos transacciones correctas. Los tres problemas son: El problema de la actualización perdida. El problema de la dependencia no confirmada y El problema del análisis inconsistente. 3.1.1.- El Problema de la Actualización Perdida. I.T.C.J. 49 Bases de Datos II Unidad III Considerarse la situación que se ilustra en la siguiente figura. Transacción A Tiempo Transacción B --- --- --- --t1 Recuperar t --- --- --- Recuperar t t2 --- --- Actualizar t --- t3 --- --- --- --- --- t4 Actualizar t --- Esta figura debería leerse de la siguiente forma: la transacción A recupera la tupla t en el tiempo t1; la transacción B recupera la misma tupla t en el tiempo t2; la transacción A actualiza la tupla en el tiempo t3 (con base en los valores vistos en el tiempo t1), y la transacción B actualiza la misma tupla en el tiempo t4 (con base en los valores vistos en el tiempo t2, que son los mismos vistos en el tiempo t1). La actualización de la transacción A se pierde en el tiempo t4, ya que la transacción B la sobre escribe sin siquiera mirarla 3.1.2.- El Problema de la Dependencia No Confirmada. El problema de la dependencia no confirmada se presenta al permitir que una transacción recupere, o lo que es peor, actualice una tupla que ha sido actualizada por otra transacción pero que aún no ha sido confirmada por esa misma transacción. Puesto que no ha sido confirmada, sigue existiendo la posibilidad y de que en su lugar se deshaga mediante un ROLLBACK; en cuyo caso, la primera transacción habrá visto datos que ya no existen (y en cierto sentido nunca existieron). Considerar las siguientes figuras. En el primer ejemplo la transacción A ve una actualización no confirmada en el tiempo t2 (llamada también cambio no confirmado). Esta actualización posteriormente deshecha en el tiempo t3. Por lo tanto, la transacción A está operando sobre una suposición falsa; Transacción A Tiempo --I.T.C.J. Transacción B --- 50 Bases de Datos II Unidad III ----- --t1 Actualizar t --Recuperar t ----- t2 ----- --t3 ROLLBACK --- La transacción A llega a ser dependiente de un cambio no confirmado en el tiempo t2. Transacción A Tiempo Transacción B --- --- --- --- --- t1 --Actualizar t --t2 ----- Actualizar t ----- t3 ROLLBACK --- La transacción A actualiza un cambio no confirmado en el tiempo t2 y pierde esa actualización en el tiempo t3. es decir, la suposición de que la tupla t tiene el valor visto en el tiempo t2, siendo que tiene el valor que tenía antes del tiempo t1. Por consecuencia, la transacción A producirá una salida incorrecta. Observar además que el hecho de que la transacción B se haya deshecho probablemente no se deba a una falla de B, sino que (por ejemplo) puede ser el resultado de una caída del sistema. (Y podría ser que la transacción A ya hubiera terminado en ese momento; en cuyo caso, la falla no permitiría una instrucción ROLLBACK para A). En el segundo ejemplo (segunda figura) es aún peor. La transacción A no sólo llega a ser dependiente del cambio no confirmado en el tiempo t2, sino que de hecho pierde una actualización en el tiempo t3, debido a que la instrucción ROLLBACK en ese tiempo hace que la tupla t sea restaurada a su valor anterior al tiempo t1. esta es otra versión del problema de la actualización perdida. 3.1.3.- El Problema del Análisis Inconsistente. I.T.C.J. 51 Bases de Datos II Unidad III Considerar en la figura siguiente que muestra dos transacciones A y B, operando sobre tuplas de una cuenta (ACC): La transacción A está sumando saldos de cuenta y la transacción B está transfiriendo una cantidad de 10 de la cuenta 3 a la cuenta 1. el resultado de 110 producido por A es obviamente incorrecto; y si A continuar y escribiera ese resultado en la base de datos, dejaría en efecto a la base de datos en un estado inconsistente. Decimos que A ha visto un estado inconsistente de la base de datos y por lo tanto, ha realizado un análisis inconsistente. Observar la diferencia entre este ejemplo y el anterior: aquí no hay posibilidad de que A sea dependiente de un cambio no confirmado, ya que B confirma todas sus actualizaciones antes de que A vea a ACC3 . ACC 1 ACC 2 ACC 3 40 50 Transacción A Tiempo Transacción B --- --- --- --- Recuperar ACC 1: --- t1 Suma = 40 --- --- RecuperarACC 2: Suma =90 --- t2 ----- --- t3 --- Recuperar ACC 3 --- --- Actualizar ACC 3: t4 --- 30 20 --- --- t5 --- Recuperar ACC 1 --- --- t6 --- Actualizar ACC 1: 40 50 --- --- t7 ----Recuperar ACC 3: t8 Suma = 110, y no 120 --- La transacción A realiza un análisis inconsistente 3.2.-EL BLOQUEO Y SUS PROTOCOLOS. I.T.C.J. 30 52 COMMIT Bases de Datos II Unidad III Una forma de asegurar la secuenciabilidad es exigir que el acceso a los elementos de datos se hagan en exclusión mutua; es decir, mientras una transacción accede a un elemento de datos, ninguna otra transacción puede modificar dicho elemento. El método más habitual que se usa para implementar este requisito es permitir que una transacción acceda a un elemento de datos sólo si posee actualmente un bloqueo sobre dicho elemento. 3.2.1.- Bloqueos. Existen muchos modos mediante los cuales se puede bloquear un elemento de datos. En este apartado se centra la atención en dos de dichos modos: 1. Compartido. Si una transacción Ti obtiene un bloqueo en modo compartido (denotado por C) sobre el elemento Q, entonces Ti puede leer Q pero no lo puede escribir. 2. Exclusivo. Si una transacción Ti obtiene un bloqueo en modo exclusivo (denotado por X) sobre el elemento Q, entonces Ti puede tanto leer como escribir Q. Es necesario que toda transacción solicite un bloqueo del modo apropiado sobre el elemento da datos Q dependiendo de los tipos de operaciones que se vayan a realizar sobre Q. La petición se hace al gestor de control de concurrencia. La transacción puede realizar la operación sólo después de que el gestor de control de concurrencia conceda el bloqueo a la transacción. 3.2.2.- Protocolo de Bloqueos de Dos Fases. Un protocolo que asegura la secuenciabilidad es el protocolo de bloqueo de dos fases. Este protocolo exige que cada transacción realice las peticiones de bloqueo y desbloqueo de dos fases. 1. Fase de Crecimiento. Una transacción puede obtener bloqueos pero no puede liberarlos. 2. Fase de Decrecimiento. Una transacción puede liberar bloqueos pero no puede obtener ninguno nuevo. I.T.C.J. 53 Bases de Datos II Unidad III Inicialmente una transacción está en la fase de crecimiento. La transacción adquiere los bloqueos que necesite. Una vez que la transacción libera un bloqueo, entra en la fase de decrecimiento y no puede realizar más peticiones de bloqueo. Por ejemplo, las transacciones T3 y T4 son de dos fases. Por otro lado, las transacciones T1 y T2 no son de dos fases. Nótese que no es necesario que las instrucciones de desbloqueo aparezcan al final de la transacción. Por ejemplo, en el caso de la transacción T3 se puede trasladar la instrucción desbloquear(B) hasta justo antes de la instrucción bloquear-X(A) y se sigue cumpliendo la propiedad del bloqueo de dos fases. Se puede mostrar que el protocolo de bloqueo de dos fases asegura la secuenciabilidad en cuanto a conflictos. Considérese cualquier transacción. El punto de la planificación en el cual la transacción obtiene su bloqueo final (el final de la fase de crecimiento) se denomina punto de bloqueo de la transacción. Ahora se pueden ordenar las transacciones en base a sus puntos de bloqueo; de hecho, esta ordenación es un orden de secuenciabilidad para las transacciones. El protocolo de bloqueo de dos fases no asegura la ausencia de interbloqueos. Observar que las transacciones T3 y T4 son de dos fases pero en la planificación 2(siguiente figura) llegan a un interbloqueo. T3 T4 Bloquear-X(B) Leer(B) B:=B-50 Escribir(B) Bloquear-C(A) Leer(A) Bloquear-C(B) Bloquear-X(A) Planificación 2 Hay que recordar que las planificaciones, además de ser secuenciales, es aconsejable que sean sin cascada. El retroceso en cascada puede ocurrir en el bloqueo de dos fases. Como ejemplo considerarse la planificación parcial de la siguiente figura. Cada transacción sigue el protocolo de bloqueo de dos fases pero un fallo de T5 después del paso leer(A) de T7 lleva a un retroceso en cascada de T6 y T7. I.T.C.J. 54 Bases de Datos II Unidad III T5 T6 T7 Bloquear-X(A) Leer(A) Bloquear-C(B) Leer(B) Escribir(A) Desbloquear(A) Bloquear-X(A) Leer(A) Escribir(A) Desbloquear(A) Bloquear-C(A) Leer(A) Planificación Parcial con Bloqueo de Dos Fases Los retrocesos en cascada se pueden evitar por medio de una modificación del protocolo de bloqueo de dos fases que denomina protocolo de bloqueo estricto de dos fases. Este protocolo exige que, además de que el bloqueo sea de dos fases, una transacción debe poseer todos los bloqueos en modo exclusivo que tome hasta que dicha transacción se complete. Este requisito asegura que todo dato que escribe una transacción no comprometida está bloqueado en modo exclusivo hasta que la transacción se completa, evitando que ninguna otra transacción lea el dato. Otra variante del bloqueo de dos fases es el protocolo de bloqueo riguroso de dos fases, el cual exige que se posean todos los bloqueos hasta que se comprometa la transacción. Se puede comprobar fácilmente que con el bloqueo riguroso de dos fases se pueden secuenciar las transacciones en el orden en que se comprometen. Muchos sistemas de bases de datos implementan tanto el bloqueo estricto como el bloqueo estricto de dos fases. Considérese las dos transacciones siguientes de las que sólo se muestran algunas de las operaciones leer y escribir significativas: T8: leer(a1); leer(a2); …. leer(an); escribir(a1). T9: leer(a1); leer(a2); visualizar(a1 + a2 ). I.T.C.J. 55 Bases de Datos II Unidad III Si se emplea el protocolo de bloqueo de dos fases entonces T8 debe bloquear a1 en modo exclusivo. Por tanto, toda ejecución concurrente de ambas transacciones conduce a una ejecución secuencial. Nótese sin embargo que T8 sólo necesita el bloqueo en modo exclusivo sobre a1 al final de su ejecución, cuando escribe a1. Así, si T8 pudiera bloquear inicialmente a1 en modo compartido y después pudiera cambiar el bloqueo a modo exclusivo, se obtendría una mayor concurrencia, ya que T8 y T9 podrían acceder a a1 y a2 simultáneamente. Esta observación lleva a un refinamiento del protocolo de bloqueo de dos fases básico en el cual se permiten conversiones de bloqueo. Se va ha proporcionar un mecanismo para cambiar un bloqueo compartido por un bloqueo exclusivo y un bloqueo exclusivo por uno compartido. Se denota la conversión del modo compartido al modo exclusivo como subir, y la conversión del modo exclusivo al modo compartido como bajar. No se puede permitir la conversión de modos arbitrariamente. Por el contrario, la subida puede tener lugar sólo en la fase de crecimiento, mientras que la bajada puede tener lugar sólo en la fase de decrecimiento. Volviendo al ejemplo, las transacciones T8 y T9 se pueden ejecutar concurrentemente bajo el protocolo de bloqueo de dos fases refinado, como muestra la planificación incompleta de la siguiente figura, en la cual sólo se muestran algunas de las operaciones de bloqueo. T8 T9 Bloquear-C(a1) Bloquear-C(a1) Bloquear-C(a2) Bloquear-C(a2) Bloquear-C(a3) Bloquear-C(a4) Desbloquear(a1) Desbloquear(a2) Bloquear-C(an) Subir(a1) Planificación incompleta con conversión de bloqueos I.T.C.J. 56 Bases de Datos II Unidad III Nótese que se puede forzar a esperar a una transacción que intente subir un bloqueo sobre un elemento Q. Esta espera forzada tiene lugar si Q está bloqueado actualmente por otra transacción en modo compartido. Del mismo modo que el protocolo de bloqueo de dos fases básico, el bloqueo de dos fases con conversión de bloqueos genera sólo planificaciones secuenciables en cuanto a conflictos y se pueden secuenciar las transacciones según sus puntos de bloqueo. Además, si se poseen los bloqueos hasta el final de la transacción, las planificaciones son sin cascada. Para un conjunto de transacciones puede haber planificaciones secuenciables en cuanto a conflictos que no puedan obtener por medio del protocolo de bloqueo de dos fases. Sin embargo, para obtener planificaciones secuenciables en cuanto a conflictos por medio de protocolos de bloqueo que no sean de dos fases, es necesario o bien tener información adicional de las transacciones o bien imponer alguna estructura u orden en el conjunto de elementos de datos de la base de datos. En ausencia de esta información es necesario el bloqueo de dos fases para la secuenciabilidad en cuanto a conflictos si Ti no es una transacción de dos fases, siempre es posible encontrar otra transacción Tj que sea de dos fases tal que existe una planificación posible para Ti y Tj que no sea secuenciable en cuanto a conflictos. Los bloqueos estricto de dos fases y riguroso de dos fases(con conversión de bloqueos) se usan ampliamente en sistemas de bases de datos comerciales. Un esquema simple pero de uso extendido genera automáticamente las instrucciones apropiadas de bloqueo y desbloqueo para una transacción, basándose en peticiones de lectura y escritura desde la transacción: Cuando una transacción Ti realiza una operación leer(Q), el sistema genera una instrucción bloquear-C(Q) seguida de una instrucción leer(Q). Cuando Ti realiza una operación escribir(Q), el sistema comprueba si Ti posee ya un bloqueo en modo compartido sobre Q. Si es así, entonces el sistema genera una instrucción subir(Q) seguida de la instrucción escribir(Q). En otro caso el sistema genera una instrucción bloquear-X(Q) seguida de la instrucción escribir(Q). Todos los bloqueos que obtenga una transacción no se desbloquean hasta que dicha transacción se comprometa o aborte. I.T.C.J. 57 Bases de Datos II Unidad III Con el siguiente ejemplo compruebe que las siguientes instrucciones llegan a un interbloqueo (practica) CREATE TABLE Cheques (num_cta INT NOT NULL, apellidos CHAR(30) NOT NULL, balance MONEY NOT NULL ) GO CREATE TABLE Ahorros (num_cta INT NOT NULL, apellidos CHAR(30) NOT NULL, balance MONEY NOT NULL ) GO INSERT cheques VALUES(1, ‘Games’, $500.00) INSERT cheques VALUES(2, ‘Valdés’, $300.00) INSERT Ahorros VALUES(1, ‘Games’, $100.00) INSERT Ahorros VALUES(2, ‘Valdés’, $200.00) GO 3.2.3.- Implementación de Bloqueos. Un gestor de bloqueos se puede implementar como un proceso que recibe mensajes de transacciones y envía mensajes como respuesta. El proceso gestor de bloqueos responde a los mensajes de solicitud de bloqueo con mensajes de concesión de bloqueo, o con mensajes que solicitan un retroceso de la transacción (en caso de interbloqueos). Los mensajes de desbloqueo tan sólo requieren un reconocimiento como respuesta, pero pueden dar lugar a un mensaje de concesión para otra transacción que esté esperando. El gestor de bloqueos utiliza la siguiente estructura de datos: Para cada elemento de datos que está actualmente bloqueado, mantiene una lista enlazada de registros, uno para cada solicitud, en el orden en el que llegaron las solicitudes. Utiliza una tabla de asociación, indexada por el nombre del elemento de datos, para encontrar la lista enlazada (si la hay) para cada elemento de datos; esta tabla se denomina tabla de bloqueos. Cada registro de la lista enlazada de cada elemento de datos anota qué transacción hizo la solicitud, y qué modo de bloqueo se solicitó. El registro también anota si la solicitud ya se ha concedido. En la siguiente figura muestra un ejemplo de una tabla de bloqueos. La tabla contiene bloqueos para cinco elementos de datos distintos: E4, E7, E23, E44 y E912. I.T.C.J. 58 Bases de Datos II Unidad III E23 E7 T23 T1 T2 T8 E912 T23 E4 T1 T23 E44 T8 Figura: Tabla de Bloqueos La tabla de bloqueos utiliza cadenas de desbordamiento, de forma que hay una lista enlazada de elementos de datos por cada entrada de la tabla de bloqueos. También hay una lista de transacciones a las que se les han concedido bloqueos, o que están esperando para bloquear, para cada uno de los elementos de datos los bloqueos concedidos se han representado como rectángulos rellenos (negros), mientras que las solicitudes en espera son los rectángulos vacíos. Se ha omitido el modo de bloqueo para que la figura sea más sencilla. Por ejemplo, se puede observar que a T23 se le han concedido bloqueos sobre E912 y E7, y está esperando para bloquear E4. Aunque la figura no lo muestre, la tabla de bloqueos debería mantener también un índice de identificadores de transacciones, de forma que fuese posible determinar de manera eficiente el conjunto de bloqueos que mantiene una transacción dada. El gestor de bloqueos procesa las solicitudes de la siguiente forma: I.T.C.J. 59 Bases de Datos II Unidad III Cuando llega un mensaje de solicitud, añade un registro al final de la lista enlazada del elemento de datos, si la lista enlazada existe. En otro caso crea una nueva lista enlazada que tan sólo contiene el registro correspondiente a la solicitud. Siempre concede la primera solicitud de bloqueo sobre el elemento de datos. Pero si la transacción solicita un bloqueo sobre un elemento sobre el cual ya se ha concedido un bloqueo, el gestor de bloqueos sólo concede la solicitud si es compatible con las solicitudes anteriores, y todas éstas ya se han concedido. En otro caso, la solicitud tiene que esperar. Cuando el gestor de bloqueos recibe un mensaje de desbloqueo de una transacción, borra el registro para ese elemento de datos de la lista enlazada correspondiente a dicha transacción. Prueba el siguiente registro, si lo hay, como se describe en el párrafo anterior, para determinar si ahora se puede conceder dicha solicitud. Si se puede, el gestor de bloqueos concede la solicitud y procesa el siguiente registro, si lo hay, de forma similar, y así sucesivamente. Si una transacción se interrumpe, el gestor de bloqueos borra cualquier solicitud en espera realizada por la transacción. Una vez que el sistema de base de datos ha realizado las acciones apropiadas para deshacer la transacción, libera todos los bloqueos que mantenía la transacción abortada. Este algoritmo garantiza que las solicitudes de bloqueo están libres de inanición, dado que una solicitud nunca se puede conceder mientras no se hayan concedido las solicitudes recibidas anteriormente. 3.3.-MARCAS TEMPORALES. En los protocolos de bloqueos que se han descrito antes se determina el orden entre dos transacciones conflictivas en tiempo de ejecución a través del primer bloqueo que soliciten ambas que traiga consigo modos incompatibles. Otro método para determinar el orden de secuenciabilidad es seleccionar previamente un orden entre las transacciones. El método más común para hacer esto es utilizar un esquema de ordenación por marcas temporales. I.T.C.J. 60 Bases de Datos II Unidad III 3.3.1.- Marcas Temporales. A toda transacción Ti del sistema se le asocia una única marca temporal fijada, denotada por MT(Ti). El sistema de base de datos asigna esta marca temporal antes de que comience la ejecución de Ti. Si a la transacción Ti se le ha asignado la marca temporal MT(Ti) y una nueva transacción Tj entra en el sistema, entonces MT(Ti) < MT(Tj). Existen dos métodos simples para implementar este esquema: 1. Usar el valor del reloj del sistema como marca temporal; es decir, la marca temporal de una transacción es igual al valor del reloj en el momento en el que la transacción entra en el sistema. 2. Usar un contador lógico que se incrementa cada vez que se asigna una nueva marca temporal; es decir, la marca temporal de una transacción es igual al valor del contador en el momento en el cual la transacción entra en el sistema. Las marcas temporales de las transacciones determinan el orden de secuencia. De este modo, si MT(Ti) < MT(Tj) entonces el sistema debe asegurar que toda planificación que produzca es equivalente a una planificación secuencial en la cual la transacción Ti aparece antes que la transacción Tj. Para implementar este esquema se asocia a cada elemento de datos Q de valores de marca temporal: • Marca_Temporal-E(Q) denota la mayor marca temporal de todas las transacciones que ejecutan con éxito escribir(Q). • Marca_Temporal-L(Q) denota la mayor marca temporal de todas las transacciones que ejecutan con éxito leer(Q). Estas marcas temporales se actualizan cada vez que se ejecuta una nueva operación leer(Q) o escribir(Q). 3.3.1.- Protocolo de Ordenación por Marcas Temporales. El protocolo de ordenación por marcas temporales asegura que todas las operaciones leer y escribir conflictivas se ejecutan en el orden de las marcas temporales. Este protocolo opera como sigue: I.T.C.J. 61 Bases de Datos II Unidad III 1. Supongase que la transacción Ti ejecuta leer(Q). a. Si MT(Ti) < Marca_Temporal-E(Q) entonces Ti necesita leer un valor de Q que ya se ha sobrescrito. Por tanto se rechaza la operación leer y Ti se retrocede. b. Si MT(Ti) Marca_Temporal-E(Q) entonces se ejecuta la operación leer y Marca_TemporalL(Q) se asigna al máximo de Marca_Temporal-L(Q) y de MT(Ti). 2. Supóngase que la transacción Ti ejecuta escribir(Q). a. Si MT(Ti) < Marca_Temporal-L(Q) entonces el valor Q que produce Ti se necesita previamente y el sistema asume que dicho valor no se puede producir nunca. Por tanto, se rechaza la operación escribir y Ti se retrocede. b. Si MT(Ti) < Marca_Temporal-E(Q) entonces Ti está intentando escribir un valor de Q obsoleto. Por tanto, se rechaza la operación escribir y Ti se retrocede. c. En otro caso se ejecuta la operación escribir y MT(Ti) se asigna a Marca_Temporal-E(Q). A una transacción Ti que el esquema de control de concurrencia haya retrocedido como resultado de la ejecución de una operación leer o escribir se le asigna una nueva marca temporal y se inicia de nuevo. Para ilustrar este protocolo considerar las transacciones T14 y T15. La transacción T14 visualiza el contenido de las cuentas A y B: T14 : Leer(B); Leer(A); Visualizar(A + B). La transacción T15 transfiere 50 Dlls de la cuenta A la B y muestra después el contenido de ambas T15 : Leer(B); B:=B - 50; Escribir(B); Leer(A); A:=A + 50; Escribir(A); Visualizar(A + B). I.T.C.J. 62 Bases de Datos II Unidad III En las planificaciones actuales con el protocolo de marcas temporales se asume que a una transacción se le asigna una marca temporal inmediatamente antes de su primera instrucción. Así en la planificación de la siguiente figura MT(T14) < MT(T15) y la planificación con el protocolo de marcas temporales es posible. T14 T15 Leer(B) Leer(B) B:=B – 50 Escribir(B) Leer(A) Leer(A) Visualizar(A + B) A:= A + 50 Escribir(A) Visualizar(A + B) Planificación 3 Notar que la ejecución anterior puede obtenerse también con el protocolo de bloqueo de dos fases. Sin embargo, existen planificaciones que son posibles con el protocolo de bloqueo de dos fases que no lo son con el protocolo de bloqueo de marcas temporales y viceversa. El protocolo de ordenación por marcas temporales asegura la secuenciabilidad en cuanto a conflictos. Esta afirmación se deduce del hecho de que las operaciones conflictivas se procesan durante la ordenación de las marcas temporales. El protocolo asegura la ausencia de interbloqueos, ya que ninguna transacción tiene que esperar. Sin embargo, existe una posibilidad de inanición de las transacciones largas si una secuencia de transacciones cortas conflictivas provoca reinicios repetidos de la transacción larga. Si se descubre que una transacción se está reiniciando de forma repetida, es necesario bloquear las transacciones conflictivas de forma temporal para permitir que la transacción termine. El protocolo puede generar planificaciones no recuperables. Sin embargo, se puede extender para producir planificaciones recuperables de una de las siguientes formas: • La recuperabilidad y la ausencia de cascadas se pueden asegurar realizando todas las escrituras juntas al final de la transacción. Las escrituras tienen que ser atómicas en el siguiente sentido: mientras que las I.T.C.J. 63 Bases de Datos II Unidad III escrituras están en progreso, no se permite que ninguna transacción acceda a ninguno de los elementos de datos que se han escrito. • La recuperabilidad y al ausencia de cascadas también se pueden garantizar utilizando una forma limitada de bloqueo, por medio de la cual las lecturas de los elementos no comprometidos se posponenhasta que la transacción haya actualizado el elemento comprometido. • La recuperabilidad sola se puede asegurar realizando un seguimiento de las escrituras no comprometidas y sólo permitiendo que una transacción Ti se comprometa después de que se comprometa cualquier transacción que escribió un valor que leyó Ti. 3.4.-SERIABILIDAD. La seriabilidad es el criterio de corrección aceptado comúnmente para la ejecución de un conjunto dado de transacciones. Para ser más precisos, se considera que la ejecución de un conjunto dado de transacciones es correcta cuando es seriable; es decir, cuando produce el mismo resultado que una ejecución serial de las mismas transacciones, ejecutando una a la vez. Ésta es la justificación de esta aseveración: 1. Las transacciones individuales son tomadas como correctas; es decir, se da por hecho que transforman un estado correcto de la base de datos en otro estado correcto. 2. Por lo tanto también es correcta la ejecución de una transacción a la vez en cualquier orden serial, y se dice, ”cualquier” orden serial debido a que las transacciones individuales son consideradas independientes entre sí. 3. Por lo tanto, una ejecución intercalada es correcta cuando equivale a alguna ejecución serial es decir, cuando es seriable. Transacción A Tiempo --- --- --Recuperar t --t1 ----- --t2 --Actualizar t Transacción B Recuperar t --t3 --- --- --- --- --- --- t4 Actualizar t --- I.T.C.J. 64 Bases de Datos II Unidad III ACC 1 ACC 2 ACC 3 40 Transacción A 50 Tiempo 30 Transacción B --- --- --- --- Recuperar ACC 1: Suma = 40 --- t1 --RecuperarACC 2: Suma =90 ----- --- t2 --- t3 --- Actualizar ACC 3: t4 --- t5 Recuperar ACC 1 --- t6 ----- 30 20 --- ----- Recuperar ACC 3 --- --- --- --- Actualizar ACC 1: 40 50 --- t7 COMMIT ----Recuperar ACC 3: Suma = 110, y no 120 t8 --- Como se en las figuras anteriores, se muestra el problema en cada caso fue que la ejecución intercalada no era seriable; es decir, la ejecución intercalada nunca fue equivalente a ejecutar A después de B, o bien B después de A. Y el efecto del esquema de bloqueo tratado en el punto (3.2 bloqueo y sus protocolos) fue precisamente forzar la seriabilidad en cada uno de los casos. 3.4.1.- Plan Serial. I.T.C.J. 65 Bases de Datos II Unidad III Terminología :Dado un conjunto de transacciones, a cualquier ejecución de esas transacciones, intercaladas o no, se le llama Plan. La ejecución de una transacción a la vez, sin intercalado, constituye un plan serial; mientras que un plan que no sea serial es intercalado (simplemente no serial). Se dice que dos planes son equivalentes cuando garantizan que producirán el mismo resultado independientemente del estado inicial de la base de datos. Por lo tanto, un plan es correcto (es decir, seriable) cuando equivale a un plan serial. El punto que vale la pena enfatizar es que dos planes seriales diferentes que involucran el mismo conjunto de transacciones bien pueden producir resultados diferentes y, por lo tanto, dos planes intercalados diferentes que involucran a esas transacciones, también pueden producir resultados diferentes, aunque ambos sean considerados como correctos. Por ejemplo supongamos que la transacción A es de la forma “sumar 1 a x” y la transacción B es de la forma “duplicar x” (donde x es algún elemento de la base de datos). Suponer también que el valor inicial de x es 10. Entonces el plan serial B después de A, da x=22; mientras que el plan serial A después de B, da x=21. estos dos resultados son igualmente correctos y cualquier plan que garantice que sea equivalente a B después de A o bien a A después de B, también es correcta. 3.5.-GRANULARIDAD. En los esquemas de control de concurrencia que se han descrito antes se ha tomado cada elemento de datos individual como la unidad sobre la cual se producía la sincronización. Sin embargo, hay circunstancias en las que puede ser conveniente agrupar varios elementos de datos y tratarlos como una unidad individual de sincronización. Por ejemplo, si la transacción Ti tiene que acceder a toda la base de datos y se usa un protocolo de bloqueo, entonces Ti debe bloquear cada elemento de la base de datos. Ejecutar estos bloqueos produce claramente un consumo de tiempo. Sería mejor que Ti pudiera realizar una única petición de bloqueo para bloquear toda la base de datos. Por otro lado, si la transacción Tj necesita acceder sólo a unos cuantos datos no sería necesario bloquear toda la base de datos, ya que en ese caso se perdería la concurrencia. Lo que se necesita es un mecanismo que permita al sistema definir múltiples niveles de granularidad. Se puede hacer uno permitiendo que los elementos de datos sean de varios tamaños y definiendo una jerarquía de granularidades de los datos, en la cual las granularidades pequeñas están anidadas en otras más grandes. I.T.C.J. 66 Bases de Datos II Unidad III Una jerarquía tal se puede representar gráficamente como un árbol. Un nodo interno del árbol de granularidad múltiple representa los datos que se asocian con sus descendientes. Como ejemplo considerar el árbol de la siguiente figura, el cual consiste en cuatro niveles de nodos. BD Aa ra1 ra2 rb1 ran ........... Z1 Z2 Ab Ac ..... ..... . rbk rc1 .... .... ... rcm Figura: Jerarquía de Granularida. El nivel superior representa toda la base de datos. Después de éste están los nodos de tipo zona; la base de datos consiste en estas zonas exactamente. Cada zona tiene nodos de tipo archivo como hijos. Cada zona contiene exactamente aquellos archivos que sean sus nodos hijos. Ningún archivo está en más de una zona. Finalmente cada archivo tiene nodos de tipo registro. Como antes, un archivo consiste exactamente en aquellos registros que sean sus nodos hijos y ningún registro puede estar presente en más de un archivo. Se puede bloquear individualmente cada nodo del árbol. Como ya se hizo con anteriormente con el protocolo de bloqueo de dos fases, se van a usar los modos de bloqueo compartido y exclusivo. Cuando una transacción bloquea un nodo, tanto en modo compartido como exclusivo, también bloquea todos los descendientes de ese nodo con el mismo modo de bloqueo. Por ejemplo si la transacción Ti bloquea explícitamente el archivo Ac de la figura anterior en modo exclusivo, entonces bloquea implícitamente en modo exclusivo todos los registros que pertenecen a dicho archivo. No es necesario que bloquee explícitamente cada registro individual de Ac. I.T.C.J. 67 Bases de Datos II Unidad III 3.6.-INTERBLOQUEOS. Ya se vio la forma en que se puede usar bloqueos para resolver los tres problemas básicos de la concurrencia. Sin embargo, desafortunadamente también hemos visto que el bloqueo puede introducir problemas por sí solo, principalmente el problema del Bloqueo Mortal. El bloqueo mortal es una situación en la que dos o más transacciones se encuentran en estados simultáneos de espera, cada una de ellas esperando que alguna de las demás libere un bloqueo para poder continuar. En la siguiente figura muestra un Bloqueo Mortal que involucra a dos transacciones, pero también son posibles, al menos en principio, bloqueos mortales que involucren a tres, cuatro, o más transacciones. Sin embargo, se quiere hacer notar que los experimentos con el System R mostraron aparentemente que en la práctica los bloqueos mortales casi nunca involucran a más de dos transacciones. Transacción A Tiempo Transacción B --- --- --- --- BLOQUEO r1 EXCLUSIVO --- t1 ----- --t2 BLOQUEO r2 EXCLUSIVO --BLOQUEO r2 EXCLUSIVO ----- t3 Espera Espera --t4 BLOQUEO r1 EXCLUSIVO Espera Espera Espera Espera Figura: Ejemplo de Bloqueo Mortal Si ocurre un interbloqueo es preferible que el sistema lo detecte y lo rompa. La detección del interbloqueo implica la detección de un ciclo en el grafo de espera (es decir, el grafo de “quien está esperando a quién”). La ruptura del bloqueo mortal implica seleccionar del ciclo del grafo como víctima y entonces deshacerla liberando por lo tanto sus bloqueos y permitiendo que continúen las demás transacciones. NOTA: en la práctica no todos los sistemas detectan los bloqueos mortales, sino que algunos usan un mecanismo de tiempo y asumen simplemente que una transacción que no ha realizado algún trabajo durante cierto periodo preestablecido, está bloqueada mortalmente. I.T.C.J. 68 Bases de Datos II Unidad III De paso, observar que la víctima ha “fallado” y ha sido deshecha sin ser culpable. Algunos sistemas volverán a iniciar esta transacción desde el principio, bajo la suposición de que las condiciones que causaron el bloqueo mortal probablemente ya no existirán. Otros sistemas simplemente regresan un código de excepción “víctima de bloqueo mortal” hacia la aplicación, y es asunto del programa manejar la situación de forma adecuada. El primero de estos dos enfoques es preferible desde el punto de vista del programador. Pero incluso si el programador tiene que involucrarse de vez en cuando, siempre es preferible ocultar el problema ante el usuario final, por razones obvias. 3.6.1a TÉCNICAS PARA PREVENIRLO Los métodos de corregir un deadlock una vez que ya se presentó éste conllevan la pérdida de tiempo y no de información, ya que las transacciones puedes abortarse de manera segura debido a las facilidades de las bitácoras, el protocolo de bloqueo de dos fases y el protocolo commit de dos fases. El método de prevención del deadlock también hace necesario abortar transacciones y siempre serán las transacciones más nuevas o jóvenes las abortadas para evitar los deadlocks. Existen dos métodos: el método apropiativo y el no apropiativo. Ambos se basan en la hora en que las transacciones son creadas, podemos hablar entonces de transacciones viejas y jóvenes. En el método no apropiativo, si una transacción Ta pide un recurso bloqueado por Tb, se permite que Ta espere solamente si Ta es más vieja que Tb. Ta es reinicializada si es más joven que Tb, conservando siempre su antigüedad. Lo que se consigue con el método no apropiativo es que ninguna transacción joven esperará por las transacciones viejas, eliminando la condición de espera circular distribuida. En el método apropiativo la regla es la inversa: Si Ta pide un bloqueo sobre un recurso cuyo dueño es Tb, se le permite esperar si Ta es más joven que Tb. Si Ta es más vieja, no espera sino que Tb es abortada por ser más joven y luego se reinicializa conservando su antigüedad. También podemos anular alguna de las 4 condiciones necesarias para que se produzca un deadlock: No puede ser anulada porque existen recursos que deben ser usados en modalidad exclusiva. La alternativa sería hacer que todos los procesos solicitaran todos los recursos que habrán de utilizar antes de utilizarlos al momento de su ejecución lo cual sería muy ineficiente. Para anular esta condición cuando un proceso solicita un recurso y este es negado el proceso deberá liberar sus recursos y solicitarlos nuevamente con los recursos adicionales. El problema es que hay recursos que no pueden ser interrumpidos. I.T.C.J. 69 Bases de Datos II Unidad III Espera Circular: esta estrategia consiste en que el sistema operativo numere en forma exclusiva los recursos y obligue a los procesos a solicitar recursos en forma ascendente. El problema de esto es que quita posibilidades a la aplicación. 3.6.2b TÉCNICAS PARA PREVENIRLO Si se tiene cuidado en la forma de asignar los recursos se pueden evitar situaciones de Deadlock. Supongamos un ambiente en el que todos los procesos declaren a priori la cantidad máxima de recursos que habrá de usar. Estado Seguro: un estado es seguro si se pueden asignar recursos a cada proceso (hasta su máximo) en algún orden sin que se genere Deadlock. El estado es seguro si existe un ordenamiento de un conjunto de procesos {P1...Pn} tal que para cada Pi los recursos que Pi podrá utilizar pueden ser otorgados por los recursos disponibles más los recursos utilizados por los procesos Pj,j<i. Si los recursos solicitados por Pi no pueden ser otorgados, Pi espera a que todos los procesos Pj hayan terminado. Como evitar los puntos muertos. Para evitar puntos muertos puede simplificar muchas de elecciones alternativas. Los esquemas para evitar estos casos imponen a los usuarios restricciones que pueden resultar difíciles de aceptar. Existen cuatro enfoques para puntos muertos: 1.- Reparación posterior: No utilizar seguros y arreglar después las fallas por inconsistencia. 2.- No bloquear: Solamente afectar a quienes efectuaron solicitudes que provocaron reclamaciones en conflicto. 3.- Asignación Previa: Si existe algún conflicto, quitar los objetos a sus propietarios. 4.- Aseguramiento de dos fases: Se realizan primero todas las reclamaciones y si ninguna esta bloqueada se inician todas las modificaciones. Reparación Posterior. El primer enfoque, es reparar posteriormente los problemas debido a no asegurar, puede responder a un valido en sistemas experimentales y educativos, pero resulta inaceptable en la mayoría de las aplicaciones comerciales. No Bloquear. El segundo enfoque asigna la responsabilidad a la transacción, el sistema proporcionara un aviso de interferencia potencial al negar la solicitud de acceso explosivo. I.T.C.J. 70 Bases de Datos II Unidad III Asignación Previa. La asignación previa de reclamaciones otorgadas a las transacciones reúne de una capacidad de “volver a enrollar”. La transacción, cuando se le notifica que no puede continuar, tiene que restaurar la base de datos y colocarse así misma en la línea de espera para un nuevo turno o el sistema tiene que eliminar la transacción, restaurar la base de datos y volver a iniciar de nuevo la transacción. Secuencia Previa. Consiste en evitar la circularidad en la secuencia de solicitud, en este caso existen 3 enfoques, vigilancia de la existencia para evitar la circularidad y aseguramiento de 2 fases, a fin de evitar puntos muertos puede vigilarse el patrón de solicitud para todas las transacciones. Aseguramiento de Dos Fases. Un enfoque simple para evitar la circularidad consiste en hacer que se reclamen previo todos los objetos antes de otorgar ningún seguro, el reclamar los recursos antes de prometer otorgar el acceso a ellos significa que posiblemente una transacción no sea capaz de concluir la fase de reclamación previa. El problema de 2 fases es que la reclamación previa puede llegar a tener que reclamar mas y mayores objetos de los que en realidad se necesita, si un calculo sobre los datos determina que objetos se necesitan después, es posible que se reclame en forma previa todo un archivo en vez de un registro. Recursos Reservados. Los puntos muertos provocados por la competencia de recursos clasificados, algunas veces se disminuye al no permitir que ninguna nueva transacción se inicie cuando la utilización llega al nivel. Esta técnica no asegura evitar los puntos muertos a menos que la reserva se conserve de un tamaño tan grande que resulte poco practico, lo suficiente para permitir que todas las transacciones activas se concluyan. I.T.C.J. 71 Bases de Datos II Unidad III Métodos de recuperación Se usan dos métodos de recuperación de base de datos: recuperación en avance o recuperación en retroceso (roll-forward o roll-back).El método a utilizar depende del tipo y la extensión de los errores. 1) Recuperación en avance Con este método se consigue la restauración mediante la copia de respaldo de la base para recuperar la porción principal de los datos. Después se reaplican los registros post-imagen del registro a la copia de respaldo para incorporar las actualizaciones efectuadas desde que se hizo la copia de respaldo. Los registros post-imagen del registro log, más que las transacciones, se reaplican ala copia de respaldo, ya que estas imágenes son datos procesados, listos para rescribirse en la base. Recuperación en retroceso Esta recuperación puede nulificar el efecto de una sola transacción que hizo cambios en la base pero abortó antes del término. (Recuerde que para mantener la integridad de los datos, una transacción debe ejecutarse en su totalidad o no ejecutarse). La recuperación en retroceso se consigue llamando al registro ante-imagen del archivo log y reinstalándolo en la base para nulificar el efecto de transacción errónea. Operación de registro La mayoría de los DBMS proporcionan un elemento de rastreo para registrar lo sucedido en cada transacción actualizada por la base de datos. El registro, es un prerrequisito para la recuperación de la base de datos; restaura un archivo a su estado anterior cuando ocurre alguna falla en una transacción. El manejador del registro (log manager), es un componente del DBMS que efectúa el registro escribiendo cualquiera de los dos tipos de registro siguiente en un archivo de búsqueda: ante-imagen: se refiere a los bloques antiguos de datos originales en la base que se guardaron antes de la actualización de una transacción. Si ocurre un error, esta copia se puede usar para cancelar el efecto de la transacción. 2) Post-imagen: es el nombre que recibe un bloque procesado por una transacción listo para ser reescrito en la base. I.T.C.J. 72