Documente Academic
Documente Profesional
Documente Cultură
Insert
Insertar una nueva pieza donde las variables anfitrionas “pno”, “pname” y “pwt”
contienen el valor para los campos “p#”, “pname” y “weight” respectivamente; los
datos del color y la ciudad son desconocidos.
EXEC SQL INSERT
INTO p (p#, pname, weight)
VALUES (:pno, :pname, :pwt);
Existen dos sentencias que pueden incluir referencias a cursors. Estas son las formas
CURREN del UPDATE y DELETE. Si un cursor “x”, por ejemplo, esta posicionado
sobre un registro particular en la base de datos, entonces es posible actualizarlo o borrar
el registro elegido del cursor “x”. Sintaxis:
SQL dinámico
Consiste en un conjunto de instrucciones de SQL inmerso que son provistas
específicamente para permitir la construcción de aplicaciones generales, en línea y
posiblemente interactivas.
Las acciones que normalmente realiza una aplicación en línea son:
• Aceptar un comando desde una Terminal
• Analizar este comando
• Elegir la sentencia SQL apropiada para la base de datos.
• Retornar un mensaje y/o el resultado a la Terminal
Si el conjunto de comandos que el programa acepta es muy pequeño, como podría ser el
caso de un programa que administra las reservaciones de líneas aéreas, entonces el
conjunto de posibles sentencias SQL a ser utilizada puede ser pequeño y además estar
escrito en “hard code” dentro del programa. En este caso, sería conveniente construir
las sentencias SQL dinámicamente, y ejecutar estas sentencias construidas
dinámicamente. Las características de SQL dinámico son provistas para asistir este tipo
de procesos.
Las dos sentencias dinámicas principales son PREPARE y EXECUTE.
Ejemplo:
sqlSource char(256);
EXEC SQL DECLARE sqlObj STATEMENT ;
sqlSource = ‘DELETE FROM SP WHERE QTY < 100’;
EXEC SQL PREPARE sqlObj FROM :sqlSource;
EXEC SQL EXECUTE sqlObj;
SqlSource es una variable del lenguaje anfitrión de tipo hilera en la cual el programa
construirá la forma origen (una construcción de texto) de alguna sentencia SQL (en el
ejemplo una sentencia DELETE). sqlObj, por contraste, es una variable SQL, no una
variable del lenguaje anfitrión que se utilizará para almacenar el objeto de la sentencia
SQL cuya forma origen está dada en sqlSource. La instrucción de asignación
“sqlSource = …;” asigna a sqlSource la forma original de una sentencia DELETE de
SQL. La sentencia PREPARE entonces toma aquellas sentencias origen, las precompila
y genera la versión ejecutable, la cual es almacenada en sqlObj. Finalmente, la
sentencia EXECUTE eejcuta la versión ejecutable y entonces ocurre la instrucción
DELETE. Información de retroalimentación de esta sentencia DELETE será retornada
en la variable SQLCA de la forma usual.
6
Unidad 4
Entorno de base de datos
Recuperación y concurrencia
Introducción
El problema de la recuperación y la concurrencia en un sistema de bases de datos está
ampliamente cubierto con el concepto de “procesamiento transaccional”. En esta
sección se tratará el significado de lo que es una transacción, el significado de un
proceso transaccional (o manejo transaccional), y lo que exactamente hacen las
instrucciones COMMIT y ROLLBACK. Finalmente, se discutirán los problemas de
concurrencia y recuperación que el concepto “transacción” intenta resolver.
Recuperación transaccional
Una transacción es una unidad lógica de trabajo. Por ejemplo, si la tabla P (tabla de
partes), se le agregara un campo adicional “TOTQTY” el cual representa la cantidad
total de pedidos para la parte en cuestión; en otras palabras, el valor de “TOTQTY” para
una parte dada es igual a la suma de todos los valores SP.QTY, tomados de todos los
registros de la tabla SP para esta parte. Ahora, si se considera la siguiente secuencia de
operaciones:
EXEC SQL WHENEVER SQLERROR GO TO UNDO ;
EXEC SQL INSERT INTO SP (S#, P#, QTY)
VALUES (‘S5’, ‘P1’, 1000) ;
EXEC SQL UPDATE P SET TOTQTY = TOTQTY + 1000
WHERE P# = ‘P1’;
EXEC SQL COMMIT;
GO TO FINISH
UNDO:
EXEC SQL ROLLBACK;
FINISH:
RETURN;
El ejemplo anterior agrega un Nuevo pedido a la tabla SP, luego, la instrucción
UPDATE actualiza el campo “TOTQTY” para la parte “P1” apropiadamente.
E punto en este ejemplo consiste en ver que presumiblemente se trata de una operación
atómica – agregar un nuevo pedido – lo cual en efecto involucra dos actualizaciones a la
base de datos. Lo que es más, la base de datos no es consistente entre las dos
actualizaciones; temporalmente, viola el requerimiento de que el valor en el campo
“TOTQTY” para la parte P1 sea igual a la suma de todos los valores SP.QTY para la
parte P1. En conclusión, una unidad lógica de trabajo (una transacción) no
necesariamente es una operación simple en la base de datos; sino, es una secuencia de
tales operaciones, en general, esto transforma un estado consistente de la base de datos,
en otro estado consistente de la base de datos, sin preservar necesariamente la
consistencia en todos sus puntos intermedios.
Ahora, es claro que no se debe permitir en el ejemplo que sólo uno de las dos
actualizaciones se ejecuten, es decir, o se ejecutan las dos actualizaciones o no se
ejecuta ninguna (porque finalmente la base de datos debe quedar en un estado
7
que fueron completadas exitosamente antes de que la falla ocurriera, pero no fueron
manejadas para obtener la transferencia de sus actualizaciones de los buffers de la base
de datos física.
El punto es: ¿Cómo sabe el sistema al momento de re-iniciar qué transacciones deshacer
y cuales rehacer? Para responder a esta pregunta, se analizará el siguiente
procedimiento: En ciertos intervalos prescritos (típicamente siempre que algún número
específico de entradas han sido escritas al log) el sistema automáticamente toma un
“checkpoint”. Tomar un checkpoint involucra:
a. Escritura física del contenido de los buffers de la base de datos hacia la base de
datos física y
b. Escritura física de un registro especial “checkpoint” hacia el log físico. El
registro checkpoint da una lista de todas las transacciones que estaban en
progreso en el momento en que el checkpoint se ejecuta. Para ver cómo esta
información es utilizada, vea la figura 4.1, la cual se debe leer como sigue:
• Una falla del sistema ocurre en el tiempo tf..
• El más reciente checkpoint, antes del tiempo tf se ejecutó en el tiempo tc
• Transacciones del tipo T1 fueron completadas antes del tiempo tc.
• Transacciones del tipo T2 empezaron antes del tiempo tc y se completaron
después del tiempo tc y antes del tiempo tf
• Transacciones del tipo T3 también empezaron antes del tiempo tc pero no
fueron completadas en el tiempo tf.
• Transacciones del tipo T4 iniciaron después del tiempo tc y se completaron
antes del tiempo tf.
• Transacciones del tipo 5 también empezaron después del tiempo tc, pero
no se habían completado en el tiempo tf.
Tiempo tc tf
T
R T1
A
N T2
S
A T3
C
C T4
I
O T5
N
E
S Fig. 4.1
Es claro, que cuando el sistema se reinicie, transacciones del tipo T3 y T5 deben ser
revertidas, y transacciones del tipo T2 y T4 deben volver a realizarse. Se debe notar, sin
embargo, que las transacciones del tipo T1 no se contemplan en el proceso de reinicio,
debido a que sus actualizaciones fueron escritas físicamente a la base de datos en el
tiempo tc como parte de el proceso checkpoint.
10
en forma unísona y además garantizarlo aún si el sistema falla en medio del proceso. El
protocolo commit de dos fases es el que habilita al coordinador para proveer esta
garantía.
A continuación, se muestra el funcionamiento del commit de dos fases. Por simplicidad
se asume que la transacción se completa exitosamente, esto es, la operación COMMIT
extendida del sistema se ejecuta (no el ROLLBACK). El coordinador recibe una
solicitud de COMMIT, entonces realiza el siguiente proceso de dos fases:
1. Primero, instruye todos los manejadores de recursos para estar listos para actuar
sobre la transacción. En la práctica, esto significa que cada manejador de
recursos debe forzar la escritura de todas las entradas del log local utilizadas por
la transacción hacia su propio log físico (por ejemplo, grabarla a un
almacenamiento no volátil, de esta forma, el manejador de recursos tendrá ahora
un registro permanente de lo que hizo en función a dicha transacción, y será
capaz de grabar permanentemente las actualizaciones o revertirlas si es
necesario). Asumiendo que la escritura forzada tiene éxito, el manejador de
recursos responde “OK” al coordinador, de lo contrario responde “NOT OK”.
2. Cuando el coordinador ha recibido las respuestas de todos los manejadores de
recursos, forza la escritura de una entrada en su propio log físico, la decisión de
almacenarlo depende de la transacción. Si todas las respuestas fueron “OK”, la
decisión es “COMMIT”; si alguna respuesta fue “NOT OK”, la decisión es
ROLLBACK. De cualquier forma, el coordinador informa a cada manejador de
recursos de su decisión, y cada manejador de recursos debe realizar un
COMMIT o ROLLBACK a la transacción localmente, como se instruyó. Debe
de tomarse en cuenta que cada manejador de recursos debe hacer lo que el
coordinador indica en la fase 2 – esto es el protocolo. (Note también, que la
aparición del registro de decisión en el log físico del coordinador marca la
transición de la fase 1 a la fase 2).
Ahora, si el sistema falla en algún punto durante el proceso, el proceso de reinicio
buscará por el registro de decisión en el log del coordinador. Si lo encuentra, entonces,
asumirá que la decisión fue ROLLBACK, y de nuevo el proceso habrá concluido
apropiadamente.
El manejador de comunicación de datos (DC manager) puede ser considerado como un
manejador de recursos según el sentido anterior. Esto es, los mensajes pueden ser
considerados como un recurso recuperable, como los registros de la base de datos, y el
DC manager necesita ser capaz de participar en el proceso de dos fases del COMMIT.
resultado incorrecto debido a la interferencia con una parte de otra transacción (en la
ausencia de un mecanismo de control). Los tres problemas son:
El problema de la pérdida de actualización
El problema de la dependencia a lo no confirmado (no grabado)
El problema del análisis inconsistente
FETCH R t1
t2
UPDATE R t3
UPDATE R
Fig. 4.2 t4
t1 UPDATE R
FETCH R t2
t3 ROLLBACK R
Fig. 4.3
t1 UPDATE R
UPDATE R t2
ROLLBACK R
t3
Fig. 4.4
40 50 30
…
FETCH ACC 1 (40) t1 …
Sum = 40 …
…. …
t2 …
FETCH ACC2 (50)
Sum = 50 …
… t3 FETCH ACC3 (30)
… …
… UPDATE ACC3
…
t4 30 Æ 20
… …
… FETCH ACC1 (40)
t5
… …
… …
… t6 UPDATE ACC1
… 40 Æ 50
… ….
t7 COMMIT
…
FETCH ACC3 (20)
Sum = 110 – no 120 t8
Fig. 4.5
Bloqueos
La idea básica del bloqueo es muy simple: Cuando una transacción necesita asegurar
que un objeto será utilizado por ella – normalmente un registro de la base de datos – no
lo cambiará de una manera impredecible mientras no tenga cubiertas las espaldas, es
decir, realizará primero un bloqueo sobre el objeto. El efecto del bloqueo es “bloquear
otras transacciones externas” al objeto, y esto logra prevenir un cambio en el objeto. La
primera transacción será capaz de realizar todo su proceso con la certeza de que el
objeto en cuestión se mantendrá en un estado estable por el tiempo que la transacción lo
necesite.
Ahora se muestra en detalle como funciona el bloqueo:
1. Primero, se asume la existencia de dos tipos de bloqueo, llamados bloqueos
exclusivos (X locks) y bloqueos compartidos (S locks), los cuales se definen en
los incisos 2 y 3.
2. Si la transacción A provoca un bloqueo exclusivo (X) sobre el registro R,
entonces un requerimiento desde otra transacción B para bloquear de cualquier
15
Estos tres párrafos pueden convertirse en una matriz resumida conocida como “matriz
de compatibilidad” (Ver Fig. 4.6). Esta matriz se interpreta como sigue: Considere
algún registro R; suponga una transacción A que provoca un bloqueo sobre el registro R
como se indica en los encabezados de las columnas (el guión representa que no existe
bloqueo); si otra transacción B solicita un bloqueo sobre el registro R como se indica
por las entradas de abajo, leyendo de izquierda a derecha. Una letra “N” indica un
conflicto (la solicitud de B no puede ser satisfecha y B cae en un estado de espera), y
una letra “Y” indica compatibilidad (la solicitud de la transacción B es satisfecha). La
matriz es simétrica.
X S -
X N N Y
S N Y Y
- Y Y Y
Ahora se puede entender la forma en que el bloqueo resuelve los tres problemas
descritos en las secciones previas.
FETCH R t1
S-lock sobre R
t2 FETCH R
S-lock sobre R
UPDATE R t3
Requiere X-lock sobre R
Esperar
Esperar UPDATE R
t4 Requiere X-lock sobre R
…
Esperar
Esperar
Fig. 4.7
…
La instrucción UPDATE de la transacción A en el tiempo t3 debe esperar, debido a que
requiere un X-lock sobre el registro R, pero existe un conflicto debido al S-lock que la
transacción B obtuvo también sobre R; por esa razón la transacción A queda en un
estado de espera. Por la misma razón, la transacción B queda en estado de espera en el
tiempo t4. Ahora ambas transacciones están bloqueadas, lo cual sin duda es otro
problema. La técnica de bloqueo resuelve el problema de la pérdida de actualización,
pero crea un nuevo problema llamado “deadlock”.
t1 UPDATE R
(obtiene X-lock
Sobre R)
FETCH R (solicita S- t2
lock)
Esperar
Esperar t3 ROLLBACK R
Obtiene registro R (Synchpoint)
S-lock sobre R Libera X-lock sobre R
Fig. 4.8
17
t1 UPDATE R
Obtiene X-lock sobre R
40 50 30
…
FETCH ACC1 (40) t1 …
(obtiene S-Lock sobre ACC1) …
Sum = 40 …
t2 …
….
FETCH ACC2 (50) FETCH ACC3 (30)
(obtiene S-Lock sobre ACC2) t3 (obtiene S-Lock sobre ACC3)
Sum = 50 …
… UPDATE ACC3
t4 (obtiene X-Lock sobre ACC3)
…
… 30 Æ 20
… …
t5
… FETCH ACC1 (40)
… (Obtiene S-Lock sobre ACC1)
… t6 …
… UPDATE ACC1
… (requiere X-Lock sobre ACC1)
t7 Esperar
FETCH ACC3 (20)
(requiere S-Lock sobre ACC3) Esperar
Esperar t8 ….
Esperar
…
Fig. 4.10
Deadlock
Ya se ha visto como el bloqueo puede resolver los tres problemas básicos de
concurrencia. Desafortunadamente, también introduce problemas, principalmente el
problema del “deadlock”. Anteriormente se vieron dos problemas de “deadlock”. La
figura 4.11 muestra una versión más generalizada de este problema. R1 y R2 en esta
figura representan algún objeto que puede ser bloqueado (por ejemplo registros de la
base de datos).
El “deadlock” es una situación en la cual dos o más transacciones están
simultáneamente en un estado de espera, cada una de las cuales espera a que alguna de
las otras libere el bloqueo antes de proceder. La figura 4.11 muestra un “deadlock” que
envuelve dos transacciones, pero los deadlocks normalmente involucran tres, cuatro,
etc., transacciones.
19
…
Requiere un X-Lock sobre R1 t1 …
… …
… …
… t2 Requiere un X-Lock sobre R2
… …
… …
… …
t3
Requiere X-Lock sobre R2 …
Esperar …
Esperar Requiere X-Lock sobre R1
Esperar t4
Esperar
Esperar Esperar
…
Figura 4.11