RECUPERACION EN UNA BASE DE DATOS EN CAIDAS
DEL SISTEMA.
Siempre que se introduce una transacción T en el SGBD
para ejecutarla, éste debe asegurarse de...
a) que
todas las operaciones de T se completen con éxito y su efecto quede confirmado
permanentemente en la base de datos, o
b) que
la transacción no tenga efecto alguno sobre
El SGBD no debe permitir que se apliquen a
La recuperación en un sistema
de base de datos consiste en (volver a) dejar la información de la base de
datos en un estado correcto, después de un fallo del sistema (caída) que ha
llevado la base de datos a un estado inconsistente, o por lo menos “SOSPECHOSO”
de serlo.
Los sistemas de base de datos pequeños no suelen proporcionar soporte
para la recuperación. Sí lo hacen los grandes sistemas de base de datos
(sistemas multiusuario...).
Los problemas de recuperación frente
a fallos y de control de la concurrencia
en un sistema de base de datos están muy relacionados con conceptos de procesamiento de transacciones.
CLASIFICACION DE LOS FALLOS DE UN SISTEMA DE BASES DE DATOS.
Existen diversas causas por las que el sistema de bases de datos puede
fallar. Algunos tipos de fallos son los siguientes:
1. ERRORES LOCALES PREVISTOS POR
2. ERRORES LOCALES NO PREVISTOS (overflow,
división por cero...) Error de
programación o al provocar una interrupción (ctrl-C
en entornos Unix...). Un fallo local sólo afecta a la transacción que se está
ejecutando donde ha ocurrido el fallo. Normalmente supone la pérdida de los
datos en memoria principal y en los buffers de
entrada/salida.
3. FALLOS
POR IMPOSICION DEL CONTROL DE CONCURRENCIA.
El Subsistema de Control de Concurrencia puede decidir abortar una
transacción T (para reiniciarla posteriormente) bien porque viola la seriabilidad o porque varias transacciones están en un
estado de bloqueo mortal y se ha seleccionado T como víctima.
4. FALLOS
DEL SISTEMA (caídas suaves)
Consisten en un mal funcionamiento del hardware o errores software (del SGBD o del SO) que afectan a todas las transacciones en
progreso de ejecución en el sistema de BD. No dañan
físicamente el disco (el contenido de
5. FALLOS
DE DISCO (caídas duras)
Son fallos en los dispositivos de almacenamiento (por ejemplo, si ocurre
una rotura de una cabeza lectora/escritora en disco, si funciona mal el
procedimiento de lectura/escritura en disco o si ocurre un fallo en la
transferencia de datos). Afectan a todas las transacciones en curso y suponen
la pérdida de información en disco (es decir, algunos bloques del disco pueden
perder sus datos).
6. FALLOS CATASTROFICOS O FISICOS
Algunos ejemplos son: corte del suministro eléctrico, robo del disco,
incendio, sabotaje, sobreescritura en discos o cintas
por error, etc. Los fallos de tipo 5 y 6 suceden con menos frecuencia y su
recuperación es más complicada.
El módulo componente del SGBD, encargado de que el sistema de base de datos sea
seguro frente a posibles fallos, es el Subsistema Gestor de Recuperación, cuya función es velar por, entre otras
cosas, que...
- las transacciones no se
pierdan (es decir, que se ejecuten),
- las
transacciones no se realicen parcialmente (deben ejecutarse en su totalidad),
- no
se ejecute una operación más de una vez o, si se hace, que el resultado sea
equivalente al obtenido si se hubiera realizado una única vez.
La recuperación de fallos en las transacciones suele equivaler a la
restauración de
La cuestión es que, cuando ocurre un fallo...
¿Cómo podemos recuperar un estado consistente de la base de datos? ¿Cómo
deshacer los cambios realizados por las transacciones que quedaron a medio y
han dejado
La recuperación se basa en unos principios bastante sencillos y que
pueden resumirse en una sola palabra: redundancia (redundancia de información, en el nivel fisico
y por tanto de forma transparente al usuario, pues no es visible al nivel
lógico).
Dicho de otro modo, la forma de garantizar que el estado de una base de
datos es recuperable, es asegurar que cualquier trozo de información que ésta
contiene, pueda ser reconstruido a partir de alguna otra información
almacenada, de forma redundante, en algún lugar del sistema.
Para hacer posible la recuperación del
sistema tras fallos o caídas del mismo, en primer lugar es necesario saber
cuándo se inicia, se confirma o se aborta cada
transacción, y también qué modificaciones sobre qué elementos de
El sistema se mantiene al tanto de las operaciones que realizan las
transacciones guardando esta información
en un fichero especial (fuera del área de
La bitácora es un fichero en
el que se almacena detalles sobre las operaciones efectuadas como parte de las
transacciones. En particular, respecto de las actualizaciones de los elementos
de
La bitácora se mantiene en disco, así que no le afecta ningún tipo de
fallo, salvo los de tipo 5 y 6. Además, se suele realizar periódicamente una
copia de seguridad del fichero bitácora, para protegerse contra fallos
catastróficos. Cada registro almacenado en la
bitácora se llama entrada, y será de uno de los siguientes tipos:
· < INICIAR, T > Indica que la transacción T ha comenzado (T se refiere
a un identificador de transacción único que el sistema genera de forma
automática y que identifica a cada transacción.) .
< ESCRIBIR, T, X, valor_anterior,
valor_nuevo > Indica que la transacción T ha
cambiado el valor del elemento X de
· < LEER, T, X > Indica que T leyó el valor del elemento X de la base de
datos
· < COMMIT, T > Indica que T
finalizó con éxito y su efecto puede ser confirmado en la base de datos en
disco (es decir, todos los cambios que ha realizado pueden ser consolidados o
asentados en
· < ROLLBACK, T > Indica que la
transacción T ha sido anulada (abortada, cancelada), de forma que ninguna de
sus operaciones tendrá efecto sobre la base de datos en disco (como si T nunca
se hubiera ejecutado: la transacción será revertida (todas sus operaciones
serán deshechas)).
También suponemos que todos los cambios permanentes de la base de datos ocurrendentro de transacciones, así que recuperarse de un
fallo de cierta transacción consiste en rehacer (para rehacer el efecto de una
operación ESCRIBIR de T se utiliza la entrada correspondiente en bitácora: se
cambia el valor del elemento alterado en dicha operación, por su valor_nuevo) o deshacer (Es posible deshacer el efecto de
una operación ESCRIBIR de T usando la entrada en bitácora correspondiente: se
restablece el valor del elemento alterado a su valor_anterior.
individualmente sus operaciones recuperables, a partir del contenido del
fichero bitácora. Por operación recuperable entendemos aquella susceptible de
ser deshecha o rehecha. Las operaciones de manipulación de datos (INSERT, UPDATE, DELETE, SELECT...) por ejemplo,
son operaciones recuperables. Toda operación recuperable implica la anotación
de una entrada en bitácora.
Tras una caída del sistema, se restablece un estado consistente de la
base de datos, examinando la bitácora y usando una técnica de recuperación
determinada.
Los protocolos de recuperación que evitan la reversión en cascada, no
necesitan anotar en bitácora la ejecución de operaciones LEER. Pero otros
protocolos sí las necesitan para la recuperación. Además, algunos protocolos
requieren que en las entradas de tipo ESCRIBIR siempre incluyan campos para valor_nuevo y para valor_anterior,
mientras que otros protocolos necesitan entradas ESCRIBIR más simples que sólo
incluyan el valor_nuevo, o bien, como los protocolos
estrictos, que sólo incluyan el valor anterior.
En este momento, hemos de recordar algunos conceptos acerca del
almacenamiento y el acceso a los datos almacenados en un sistema de base de
datos, para comprender cómo pueden ser garantizadas las propiedades de
atomicidad y durabilidad de las transacciones.
Cada transacción T posee un área de trabajo privada (un espacio de memoria
principal y local a dicha transacción) en la que guarda una copia de todo
elemento de información accedido y actualizado por T. Dicho área se crea cuando
T comienza y se elimina cuando T se confirma o se aborta. Por otro lado el
sistema mantiene un buffer de
BD, que
consiste en uno o varios bloques de memoria principal. También se le denomina memoria
intermedia, y es común a todas las transacciones. En este área de
memoria residen temporalmente los bloques de la base de datos, cuando las
transacciones necesitan los datos almacenados en ellos. Esta jerarquía de
almacenamiento en dos niveles que suele corresponder con el concepto de memoria virtual.
Cuando T realiza una operación de lectura, si
el elemento buscado no está ya en el buffer
de BD, se trae desde
Cuando T realiza una operación de escritura,
si el elemento que se va a modificar no está ya en la memoria intermedia, se
trae desde
Por tanto, las modificaciones realizadas por cada transacción se llevan a
cabo en su espacio local y quedan almacenadas en el buffer de
Nótese que ambas operaciones pueden necesitar la transferencia de un
bloque desde
El sistema llevará eventualmente a
· Cuando T termina de ejecutar una operación de COMMIT,
significa que:
- Todas sus operaciones de acceso a la base de datos han
sido ejecutadas
con éxito
- El efecto de tales operaciones se ha anotado en la bitácora, incluida
una última entrada <COMMIT, T>.
Así que T ha
llegado a su punto de confirmación (el final de una unidad lógica de
trabajo).
Y a partir de este momento se puede suponer que:
T está confirmada,
Los cambios que ha realizado ya han sido consolidados.
Esto significa que se ha de suponer que se han llevado a
Los cursores abiertos han sido cerrados, y los bloqueos
han sido liberados.
Cuando T ejecuta una operación de ROLLBACK,
significa que T ha sido cancelada, de forma que el sistema debe anular todas
sus operaciones (de actualización de datos), para llevar la base de datos al
estado en el que estaba justo antes de que se iniciara T.
Notas:
Una operación COMMIT o ROLLBACK finaliza una transacción, no un programa. La
ejecución de un programa suele consistir en una secuencia de transacciones
ejecutadas una tras otra.
El punto de confirmación es un concepto lógico; no queda
reflejado físicamente como tal en ningún lugar.
Supongamos que se están ejecutando varias transacciones de forma
concurrente. Dichas transacciones habrán realizado modificaciones sobre
elementos de
Está claro que una vez que el sistema es reiniciado, deberán ser
anuladas aquellas transacciones T que
han quedado a medio, puesto que no alcanzaron su punto de
confirmación (son aquellas que no llegaron a anotar su <COMMIT,
T> en la bitácora
- Nótese que para que sea posible deshacer cambios
realizados sobre elementos de BD, es necesario que en
el fichero de bitácora existan las entradas correspondientes a dichos cambios.
¿Y qué ocurre con las transacciones que habían finalizado cuando ocurrió
el fallo?
Se podría pensar que las transacciones se confirmaron y pueden darse por
terminadas. Sin embargo, no es seguro que estas transacciones estén confirmadas
realmente, pues es posible que algún cambio sobre un elemento de
Esto ocurre si el fallo tiene lugar mientras se están grabando en disco
los elementos de
Por esto, una
vez reiniciado el sistema, es necesario rehacer las modificaciones de las transacciones que
terminaron con éxito, para asegurar que quedan realmente
consolidadas en disco (aquellas que sí llegaron a escribir <COMMIT, T> en la bitácora).
- Nótese que para que sea posible rehacer cambios, es
necesario que en el fichero de bitácora, existan las entradas correspondientes
a los mismos.
Por un lado, hemos de tener en cuenta que la bitácora es un fichero en disco.
Como ya sabemos, actualizar un fichero en disco implica:
1. copiar
el bloque adecuado del fichero en disco a un buffer de la memoria principal,
2. actualizar
el bloque en el buffer (insertar una
nueva entrada, por ejemplo) y
3. copiar el bloque desde el buffer al disco.
Esto supondría una escritura en disco cada vez que se inserta una nueva
entrada en la bitácora.
Para conseguir una única escritura por bloque, en la práctica...
- se
mantiene un bloque completo de bitácora
en memoria principal (buffer de
bitácora), y
- cuando
se llena de entradas, el bloque completo se escribe en disco (fichero bitácora)
Con esto se evita escribir varias veces en disco un mismo bloque de
fichero, pero provoca otros problemas,
que se ilustran a continuación mediante algunos ejemplos.
Supongamos un par de transacciones en ejecución, T1 y T2. Ambas realizan
actualizaciones sobre elementos de
<ESCRIBIR,T2,X,7,15>,
<ESCRIBIR,T1,Y,2,5>,
etc.
Supongamos
también que algunos de estos cambios se consolidan en
<ESCRIBIR,T1,Z,6,3>
<ESCRIBIR,T1,V,8,1>
y
<COMMIT, T1>.
El COMMIT
de T1 indica al sistema que puede confirmar en disco
los cambios (hechos por T1) aún no llevados a
Supongamos ahora que el sistema comienza a escribir en
Si el fallo ocurre justo durante la consolidación de los
cambios de
Recordemos que T2 no había
alcanzado su punto de confirmación. Cuando el sistema es reiniciado, el proceso
de recuperación accede al fichero de bitácora en disco.
Lo más normal es que el fallo haya provocado la pérdida
del contenido de la memoria principal, así que no encontrará ninguna de esas
entradas del buffer de bitácora que
todavía no se habían volcado en disco cuando ocurrió el fallo.
En particular no encontrará la entrada <COMMIT, T1> ni <COMMIT, T2>, así que intentará
anular T1 y T2.
Sin embargo T1 no debe ser
anulada, pues se realizó completamente y con éxito. Lo único que ocurre es que
no se completó la confirmación en disco de sus cambios. Tan sólo se debería
rehacer cada una de sus operaciones.
Este error se hubiera evitado si, antes de comenzar la
consolidación de cambios de BD en disco, se hubiera
grabado en disco (y con éxito, claro) la porción de bitácora que sólo estaba en
el buffer: el sistema hubiera
detectado la confirmación de T1 (pues en la bitácora
en disco estaría la entrada de COMMIT T1), y además sí sería posible rehacer las modificaciones
de T1, porque estarían en bitácora (en disco) todas
las entradas <ESCRIBIR, T1,...> .
Pero aún existe un problema adicional. Decíamos que el
sistema intentará anular T1 y T2.
Dos de las entradas perdidas a causa del fallo son
<ESCRIBIR,T2,X,7,15> y
<ESCRIBIR,T1,Y,2,5>
así que no se tiene anotado (en fichero bitácora) ni el valor_anterior ni el valor_nuevo
para X ni para Y.
Pero ambos cambios fueron llevados a
Otra entrada perdida es <ESCRIBIR,T1,Z,6,3>,
que corresponde a otro cambio de T1 que sí ha dado
tiempo a consolidar en disco antes del fallo. Pero tampoco en este caso se
puede deshacer esta operación, y por la misma razón que antes.
Vemos que es imposible recuperar la base de datos a un
estado de consistencia anterior.
Todo esto también se hubiera evitado si, antes de
comenzar la grabación de cambios de BD en disco, se
hubiera grabado en disco la porción de bitácora que sólo estaba en el buffer: sí sería posible deshacer las
modificaciones de T1 y T2 ,
porque estarían en bitácora (en disco) todas las entradas <ESCRIBIR,...>
necesarias.
En realidad, lo que hemos hecho es razonar que, para
evitar estos problemas, es necesario seguir un protocolo de bitácora
adelantada., puesto que asegurará que la base de datos podrá ser recuperada de
forma correcta.
Este protocolo indica que ...
1. No
se puede grabar en disco los cambios realizados por una transacción T 1 , hasta
que se haya forzado la escritura en disco de toda entrada de bitácora para T 1
, hasta el momento actual.
2.
La operación
confirmar de una transacción no se puede completar hasta que se haya forzado la
escritura en disco de cualquier entrada de bitácora para esa transacción .
Es decir fuerza la escritura de la bitácora en disco antes de consolidar cualquier cambio realizado por T. (ya sea para confirmar cambios en disco antes que T alcance su punto de confirmación o para confirmarlos después de que T lo haya alcanzado).
Así que nunca va a ocurrir que
1º) se lleven a disco los cambios de elementos de BD
y
2º) el sistema falle al ir a grabar en disco la parte de bitácora.
Pero sí puede ocurrir que
1º) se grabe físicamente la parte de la bitácora de una modificación y
2º) el sistema falle cuando va a aplicar el cambio a
En este último caso, al reiniciar el sistema, el Gestor de Recuperación
sabrá que la modificación pudo hacerse o no físicamente, pues está registrada
en bitácora. Podrá deshacerla o rehacerla usando la entrada correspondiente en
bitácora.
Con el uso del protocolo de bitácora adelantada, siempre estamos seguros
de que podemos llevar la base de datos a un estado consistente, aunque ocurra
un fallo mientras se graban en disco los cambios de elementos de BD, pues será posible rehacer y/o deshacer los cambios.
Retomemos ahora el proceso de recuperación, tras una caída del sistema de
BD.
Al rearrancar el sistema el Gestor de
Recuperación accede al fichero de bitácora (en disco). En él están anotadas
todas las entradas correspondientes a modificaciones sobre elementos de la base
de datos, realizadas por las transacciones. Para aquellas transacciones que
alcanzaron su punto de confirmación, también estarán anotadas las entradas COMMIT adecuadas. Así que el Gestor de Recuperación del
sistema de BD lleva a cabo las siguientes
operaciones:
1. DESHACER
(undo) las transacciones activas, es decir las que
estaban en progreso cuando ocurrió el fallo
2. REHACER
(redo) las transacciones que alcanzaron su punto de confirmación antes de la
caída, pero (quizás) no tuvieron tiempo de transferir sus actualizaciones desde
los buffers
de BD a
Y ¿cómo sabe el sistema cuáles debe rehacer?
Pues el sistema debe examinar la bitácora desde el principio, y
rastrearla hacia adelante para determinar que:
a) T
estaba activa si ha escrito una entrada <INICIAR,T>,
pero no ha escrito ninguna entrada <COMMIT,T>
ni <ROLLBACK, T>, y que
b) T
alcanzó su punto de confirmación si ha escrito <COMMIT,
T> en bitácora.
Es posible evitar tener que recorrer toda
la bitácora, en busca de las transacciones activas (para anularlas
(deshacer sus operaciones) o descartarlas, para reiniciarlas posteriormente).
También se puede evitar tener que rehacer todas
las transacciones confirmadas.
Ambas cosas se consiguen usando puntos de validación (también llamados
puntos de revisión o puntos de control).
Un punto de validación es otro tipo de entrada en la bitácora. El sistema
establece un punto de revisión de forma automática y periódica. En particular,
es el Gestor de Recuperación el que establece cuándo marcar un punto de
validación. Por ejemplo cada m minutos, o cuando se han grabado en el buffer de bitácora un número t de
entradas del tipo <COMMIT, T> desde el último
punto de validación 18 .
Marcar un punto de revisión implica lo siguiente:
1. Suspender
temporalmente la ejecución de todas las transacciones en curso.
2. Escribir
en disco todas las entradas de bitácora que residan en ese momento en el buffer de bitácora (en memoria).
3. Forzar
la escritura en disco de todos los bloques del buffer de BD que se hayan modificado (es
decir, se llevan a disco todas las actualizaciones realizadas 19 ).
4. Escribir
una entrada especial (registro de validación) en la bitácora en disco.
El registro de validación contiene:
- lista
de identificadores de las transacciones activas.(en el instante del punto de
validación)
- dirección
dentro del fichero bitácora, de la primera y última entrada correspondientes a
cada transacción activa (para rapidez de acceso si es necesario anular una
transacción)
5. Escribir
en un fichero especial de arranque del sistema, la dirección física del
registro de validación dentro del fichero bitácora. El Gestor de Recuperación
accede a este fichero especial de arranque cuando el sistema es reiniciado tras
el fallo.
6. Reanudar la ejecución de
transacciones.
Así pues, cuando ocurra un fallo sólo será necesario examinar la bitácora
desde el último punto de revisión hacia adelante, y toda transacción cuya
entrada <COMMIT, T> esté en la bitácora antes
de dicho punto de validación no deberán rehacer sus operaciones ESCRIBIR, pues
ahora estamos seguros de que fueron consolidadas por completo (ya que en el
punto de revisión se forzó la escritura en disco de tales actualizaciones).
Nota: el marcar un punto de revisión implique la escritura en disco, no
quiere decir que no existan otros momentos en los que también se consoliden
cambios en disco, aparte de en estos puntos de validación
Por otro lado, recordemos ahora que si una transacción T1 aborta (y, por tanto, es anulada), cualquierotra
T2 que haya leído elementos escritos por T1, también debería ser anulada. Esto es la reversión en cascada y puede ocurrir si
el protocolo de recuperación garantiza planes recuperables, pero no que sean
estrictos o sin cascada.
La reversión en cascada consume mucho tiempo, y por esto casi todos los
mecanismos de recuperación se diseñan de forma que nunca sea necesaria la
reversión en cascada.
Nótese que para revertir transacciones es necesario deshacer las
operaciones ESCRIBIR, y que las entradas tipo LEER se anotan en la bitácora
para determinar si es necesaria la reversión de transacciones.
Por tanto, si el método de recuperación garantiza que nunca ocurrirá
reversión en cascada, no será necesario anotar en bitácora entradas
correspondientes a lecturas de elementos.
A continuación describiremos algunas técnicas de recuperación. No son
descripciones de cómo un sistema específico implementa la recuperación, sino
que nuestra intención es describir conceptualmente varias estrategias distintas
para la recuperación de caídas del sistema de BD.
Con frecuencia las técnicas de recuperación están “ligadas” con los
mecanismos de control de la concurrencia. Es decir, algunas técnicas funcionan
mejor con unos métodos de control de concurrencia que con otros. Con todo,
analizaremos en primer lugar los conceptos de recuperación sin tener en cuenta
los mecanismos de control de la concurrencia, es decir considerando un sistema
monousuario, y después indicaremos las circunstancias en las que, si se emplea
un protocolo de control de concurrencia determinado, conviene usar un mecanismo
específico de recuperación.
Una estrategia de recuperación representativa podría resumirse
informalmente de la siguiente manera:
· Tras un fallo en el sistema (de
tipo 5 o 6) que ha producido daños en una parte considerable de
Es conveniente, por tanto realizar periódicamente una copia de seguridad
del contenido de la base de datos.
Además se debe hacer, con mayor frecuencia, una copia de respaldo del
fichero bitácora para no perder los efectos de las transacciones ejecutadas
desde la última copia de seguridad (backup) de
· Si el fallo es no catastrófico
(de los tipos
En ambos casos, consideramos que el fichero bitácora en disco (log) no sufre ningún daño.
Dos tipos fundamentales de técnicas
de recuperación de fallos no catastróficos son las técnicas basadas en la actualización diferida y en la actualización inmediata, que vamos a ver
a continuación.
TECNICA DE ACTUALIZACION DIFERIDA DE
Si el sistema sigue esta técnica, una transacción T no actualiza
Antes de ser confirmada T, todas sus actualizaciones se realizan en el
espacio de trabajo local de dicha transacción (en memoria) y son anotadas en el
buffer de bitácora (también en memoria).
Una vez que T llega a su punto de confirmación, primero se fuerza la
escritura en disco de la bitácora, y después se escriben sus actualizaciones en
… Si
T falla antes de llegar a su punto de confirmación, no habrá modificado
… Si
T falla una vez alcanzado su punto de confirmación, habrá que rehacer T (a
partir de las entradas de bitácora) porque no es seguro que todos sus cambios
se hayan llevado a disco.
Este protocolo, por tanto, quedaría definido con los siguientes puntos:
a) Una
transacción no puede modificar
b) Una
transacción no llega a su punto de confirmación antes de anotar todas sus
operaciones de actualización en bitácora y de forzar la escritura de la
bitácora en disco. Una vez se ha hecho esto, la actualización real tiene lugar,
y la transacción pasa al estado CONFIRMADA.
Si el sistema sigue esta técnica, una vez reiniciado el mismo, el Gestor
de Recuperación ejecutará el algoritmo
de recuperación NO DESHACER / REHACER:
1. Crear dos listas de transacciones 21 , llamadas ACTIVAS y CONFIRMADAS, ambas vacías.
2. Inicializar
ACTIVAS a la lista de transacciones activas que aparecen en el registro de
validación (correspondiente al último punto de revisión) escrito en la
bitácora.
3. Examinar
la bitácora a partir del último punto de revisión hacia adelante.
4. Si
se encuentra una entrada <INICIAR,T>, se añade
T a la lista ACTIVAS.
5. Si
se encuentra una entrada <COMMIT,T>, mover T de
la lista ACTIVAS a la lista CONFIRMADAS.
6. Al terminar de examinar la
bitácora,
· REHACER
las operaciones ESCRIBIR de las transacciones de la lista CONFIRMADAS, en el
mismo orden en que se escribieron en bitácora,
· REINICIAR
las transacciones de la lista ACTIVAS (transacciones en curso, no confirmadas)
Nota: las listas no almacenarán transacciones en sí, sino los
identificadores de dichas transacciones, representados con la letra T
El sistema está ahora preparado para aceptar nuevos trabajos (
Rehacer una operación ESCRIBIR realizada por T consiste en examinar su
correspondiente entrada en bitácora <ESCRIBIR,T,X,valor_nuevo>
y asignar valor_nuevo al elemento X de
Esta operación rehacer debe ser idempotente (es
decir, ejecutarla varias veces debe equivaler a ejecutarla una sola vez.
Nótese que en las entradas de bitácora tipo ESCRIBIR sólo es necesario
almacenar los valores nuevos y no los anteriores, puesto que nunca se requiere
deshacer operaciones pero sí rehacerlas.
Y reiniciar una transacción significa reintroducirla en el sistema, como
si fuera nueva. Puede hacerlo el sistema de forma automática, o el usuario
manualmente.
Si el sistema es monousuario,
en la lista ACTIVAS habrá como máximo una transacción.
Si el sistema es multiusuario,
dependiendo de los protocolos de control
de la concurrencia empleados, el proceso de recuperación puede ser más
complejo. Cuando mayor sea el grado de concurrencia, más complicada será la
tarea de recuperación:
Consideramos un sistema en el que la bitácora incluye puntos de
validación y el control de la concurrencia utiliza bloqueo de dos fases y evita
el bloqueo mortal haciendo que una transacción T obtenga, antes de comenzar a
ejecutarse, todos los bloqueos de los elementos que necesita.
Para combinar el método de recuperación por actualizaciones diferidas con
esta técnica de control de concurrencia, podemos mantener todos los bloqueos de
los elementos hasta que T llegue a su punto de confirmación.
Después de ello, los bloqueos pueden liberarse.
Esto garantiza planes estrictos y seriables.
Una desventaja de este método es que limita la ejecución concurrente de
las transacciones, pues los elementos permanecen bloqueados hasta que T llega a
su punto de confirmación.
Pero su principal ventaja es que nunca es necesario deshacer operaciones,
porque...
1) Una
transacción no modifica
2) Una
transacción T1 nunca lee un elemento modificado por
otra transacción T2 no confirmada, porque los
elementos permanecen bloqueados por T2 hasta que ésta
alcanza su punto de confirmación, luego nunca hay reversión en cascada.
Después de ello, los bloqueos pueden liberarse.
Esto garantiza planes estrictos y seriables.
Si el sistema utiliza esta técnica, es posible que algunas operaciones de
una transacción T actualicen
Recordemos que, para que sea posible la recuperación, estas
actualizaciones deben ser anotadas en la bitácora en disco antes de ser
aplicadas a
… Si
T falla después de haber llevado algunos cambios a
… Y,
por el mismo motivo que en la técnica anterior, si T falla después de alcanzar
su punto de confirmación será necesario rehacer sus operaciones.
Si el sistema sigue esta técnica, una vez reiniciado el mismo, el Gestor
de Recuperación ejecutará el algoritmo
de recuperación DESHACER / REHACER:
1. Crear dos listas de transacciones, llamadas ACTIVAS y CONFIRMADAS, ambas vacías.
2. Inicializar
ACTIVAS a la lista de transacciones activas que aparecen en el registro de
validación (correspondiente al último punto de revisión) escrito en la
bitácora.
3. Examinar
la bitácora a partir del último punto de revisión hacia adelante.
4. Si
se encuentra una entrada <INICIAR,T>, se añade
T a la lista ACTIVAS.
5. Si
se encuentra una entrada <COMMIT,T>, mover T de
la lista ACTIVAS a CONFIRMADAS.
6. Al
terminar de examinar la bitácora,
· DESHACER, con base en la bitácora, las operaciones
ESCRIBIR de las transacciones en ACTIVAS. Deben deshacerse en orden inverso a
aquel en que se anotaron en bitácora,
· REHACER, con base en la bitácora, las operaciones
ESCRIBIR de las transacciones en CONFIRMADAS, en el mismo orden en que se
escribieron en bitácora.
El sistema está ahora preparado para aceptar nuevos trabajos (
Deshacer una operación ESCRIBIR realizada por T consiste en examinar su
entrada en bitácora <ESCRIBIR,T,X,valor_anterior,valor_nuevo>
y asignar valor_anterior al elemento X de
Una variación de esta técnica
obliga a que, para que pueda decirse que t ha llegado a un punto de
confirmación, todas las actualizaciones realizadas por T deben haber sido
grabadas en la base de datos.
En este caso, si T falla una vez alcanzado su punto de confirmación, no
se necesitará rehacer nada.
Si el sistema sigue esta técnica, una vez reiniciado el mismo, ejecutará
el algoritmo de recuperación DESHACER/NO
REHACER, cuyos pasos se analizarán en base al algoritmo estudiado
anteriormente (EJERCICIO PARA EL ALUMNO
Si el sistema es monousuario,
en la lista ACTIVAS habrá como máximo una transacción.
Si el sistema es multiusuario y
se permite la ejecución concurrente, el
proceso de recuperación también depende de los protocolos empleados para el
control de la concurrencia:
Consideramos un sistema en el que la bitácora incluye puntos de
validación y el control de la concurrencia usa bloqueo de dos fases estricto,
el cual sólo permite que una transacción T lea o escriba un elemento si la
última transacción que lo ha escrito ya se ha confirmado. Esto garantiza planes
estrictos, pero pueden producirse bloqueos mortales, por lo que se necesita
deshacer transacciones.
RECUPERACION DE TRANSACCIONES MULTIPLES.
Hasta ahora hemos considerado que una transacción sólo tiene acceso a una base de datos. En algunos casos, una transacción puede necesitar acceso a varias bases de datos.
De hecho, en los sistemas llamados de múltiples bases de datos (o multibase de datos), una transacción puede acceder a las BD de varios SGBD diferentes e
independientes. Cada SGBD podría tener su propio
gestor de transacciones, su propia técnica de recuperación
Supongamos una transacción de multibase de
datos T, que modifica datos en una base de datos IMS
y también en otra base de datos DB2.
a) Si
T acaba con éxito, debe realizar COMMIT de todas sus
actualizaciones (tanto en el sistema IMS como en el
sistema DB2)
b) Si
T debe ser anulada, es necesario hacer ROLLBACK de
todas sus actualizaciones (en ambos sistemas IMS y DB2)
Es decir, NO es posible que T realice un COMMIT
en IMS y un ROLLBACK en DB2, ni tampoco puede suceder que T haga un ROLLBACK en IMS y un COMMIT en DB2, pues en estos
casos la transacción NO sería atómica.
Es necesario, por tanto, que T acabe con la misma instrucción en ambos
sistemas, es decir con dos COMMIT o dos ROLLBACK, uno en cada sistema.
Pero, aunque así sea ¿quién controla lo que ha ocurrido en el otro
sistema?
Si ocurriera un fallo a la mitad de la transacción (es decir, cuando T ya
ha hecho COMMIT en el sistema IMS,
y está a la mitad de su ejecución en DB2) tendríamos
La transacción se habría ejecutado parcialmente: violación de la
atomicidad de T.
La solución es utilizar un mecanismo de recuperación de dos niveles, que
necesita (además de los gestores de recuperación locales) un coordinador o Gestor de Recuperación
global.
El coordinador seguiría un protocolo
de confirmación en dos fases, para garantizar que los gestores de
recuperación locales (de IMS, DB2...)
hacen COMMIT o ROLLBACK de
las actualizaciones (las realizadas en cada sistema) al unísono, aunque el
sistema falle a mitad del procesamiento de la
transacción en alguno de los sistemas participantes.
Supongamos que la transacción T finaliza con éxito, lo cual implica la ejecución de un COMMIT en todos los sistemas a los que accede. Cada sistema, por tanto, envía al coordinador un mensaje indicando que la parte de T en la que participa dicho sistema, ha acabado sin problemas. Esto es similar al caso de los Sistemas de base de datos Distribuidos, donde una transacción puede interactuar con (acceder a datos almacenados en) varias fuentes de datos diferentes, puesto que la base de datos está dividida en
partes que residen en distintos sitios conectados en red.
Fase 1.
a. Cuando
todos los SGBD participantes indican al coordinador
que la parte de T en la que interviene cada uno ha acabado con éxito, el
coordinador envía a cada participante el mensaje “prepárense para confirmar la
transacción T”.
b. Cada
sistema participante fuerza la escritura en disco de todas las entradas de la
bitácora (local). De este modo cada sistema consigue un registro permanente de
las actualizaciones de T, así será capaz de consolidarlas o de anularlas, según
sea necesario.
c. Si
esta escritura se lleva a cabo sin problemas, cada sistema envía un mensaje de
“ok” o “listo para confirmar T” al coordinador. Si
falla la escritura forzada o la transacción local no puede confirmarse por
alguna razón, el sistema participante envía una señal de “no” o ”imposible
confirmar T”.
Si tras un tiempo de espera, el coordinador no recibe nada desde algún
sistema, supone que su respuesta es “no”.
Fase 2.
a. Una
vez que el coordinador ha recibido todos los mensajes, graba en su bitácora un
registro de decisión (el cual contiene todos los mensajes recibidos) y después
fuerza la escritura en disco de su bitácora.
b. Si
todos los mensajes eran de tipo “ok”, T tiene éxito y
el coordinador envía una señal “confirmar T” a todos los sistemas
participantes, para que cada uno escriba en su bitácora una entrada <COMMIT, T> y si es necesario consolide los cambios de T
en su BD (es posible recuperarse de un fallo pues
todos los efectos locales de T se han anotado en las bitácoras de las BD participantes).
Si alguno de los mensajes era de tipo “no”, T ha fallado y el coordinador
envía “anular T” a todos los sistemas participantes, para que cada uno deshaga
las actualizaciones de T individualmente, usando su propia bitácora.
Ahora, cuando cae el sistema, el procedimiento de recuperación (al rearrancar) es el siguiente:
1. El coordinador accede al
registro de decisión en su propia bitácora.
2. Si
lo encuentra, el proceso sigue por donde se quedó (segunda fase), es decir,
según los mensajes que el coordinador recibió, éste enviará “confirmar” o
“anular” a todos los sistemas participantes.
3. Si
no lo encuentra (el error tuvo lugar antes de la segunda fase), el coordinador
envía “anular” a todos los sistemas participantes.