domingo, 26 de junio de 2011

CONTROL DE CONCURRENCIA EN BASE DE DATOS

 

La mayoría de las bases de datos se utilizan en entornos multi-usuario, en los que muchos clientes utilizando la misma aplicación, o muchas aplicaciones cada una con uno o muchos clientes acceden a la misma base de datos. Cada una de esas aplicaciones enviará consultas al gestor, y normalmente cada hilo de ejecución será una transacción diferente.

En la mayoría de los sistemas operativos actuales, las diferentes tareas o hilos se ejecutan de forma intercalada (incluso en el caso de máquinas con varios procesadores). Es decir, el sistema operativo decide por su cuenta cuando suspender una de las tareas y darle un poco de tiempo de ejecución a otra. Si hay tareas simultáneas o concurrentes sobre la misma base de datos, esta intercalación puede resultar en que las lecturas y escrituras de las diferentes tareas o aplicaciones en el medio físico se realicen en cualquier orden y secuencia.

El acceso simultáneo descrito puede dar como resultados información inconsistente o simplemente incorrecta, dependiendo de la mala o buena suerte que tengamos en la intercalación de las lecturas y escrituras simultáneas. Esta problemática ha llevado a diseñar e implementar diferentes estrategias de control de concurrencia, que se encargan de evitar todos esos problemas, de modo que los desarrolladores de las aplicaciones pueden “olvidarse” de ellos al escribir su código.
Por ejemplo, si tenemos una estructura de tablas relacional que incluye las siguientes:
PEDIDO(id, num-cliente, id-prod, cantidad, precio)
PRODUCTO(id-prod, nombre, ..., stock)
...
Pueden ocurrir diferentes problemas relacionados con la escritura simultánea con otras escrituras o lecturas, incluyendo los siguientes:
  1. Dos sentencias UPDATE que actualicen un mismo producto decrementando el stock del mismo en una unidad podrían terminar en que una de ellas no se realizase. Si pensamos en un UPDATE como una secuencia de una lectura y una escritura, puede que ambos UPDATE hagan la lectura, por ejemplo, de un stock de 10, y después las escrituras, decrementan ese dato, quedando el resultado en 9, mientras que lo correcto era un resultado de 8.
  2. Supongamos una sentencia que primero comprueba que hay stock del producto P, y después inserta un nuevo PEDIDOde diez unidades del producto P, que tiene un stock de 10, seguido de un UPDATE al stock por esa cantidad. Puede que otra inserción de un pedido se ejecute antes del UPDATE pero después de la comprobación, haciendo quedar el stock del producto en negativo.
Existen varias técnicas para controlar la concurrencia. Los bloqueos son los más conocidos, aunque también se utiliza el control multi-versión y otras técnicas como las marcas de tiempo.

TECNICA DE VALIDACION OPTIMISTA

Cabe destacar que la ejecución de cualquier operación de una transacción sigue la secuencia de fases: validación , lectura , cómputo  y escritura . La técnica  de validación   optimista, retrasan la fase de validación justo antes de la fase de escritura . De esta manera, una operación sometida a un despachador optimista nunca es retrasada. Las operaciones de lectura, cómputo y escrita de cada transacción se procesan libremente sin actualizar la base de datos corriente. Cada transacción inicialmente hace sus cambios en copias locales de los datos.

La fase de validación consiste en verificar si esas actualizaciones conservan la consistencia de la base de datos. Si la respuesta es positiva, los cambios se hacen globales (escritos en la base de datos corriente). De otra manera, la transacción es abortada y tiene que reiniciar.

La técnica de validación optimista  fueron propuestos originalmente con el uso de estampas de tiempo. Sin embargo, en este tipo de mecanismos las estampas de tiempo se asocian únicamente con las transacciones, no con los datos.Más aún, las estampas de tiempo no se asignan al inicio de una transacción sino justamente al inicio de su fase de validación. Esto se debe a que las estampas se requieren únicamente durante la fase de validación

MARCA DE TIEMPO

Es una técnica que puede considerarse  dentro de las optimistas .Se asigna a cada transacción un identificador único, su marca de tiempo (tiempo de inicio).No hay bloqueos. Se retardan las actualizaciones hasta el final de la transacción.
Si una transacción quiere actualizar o consultar un dato que ha sido actualizado por una transacción de fecha posterior (más reciente), entonces se deshace y se vuelve a lanzar. Es decir si se intenta usar un dato que se ha modificado después de que la transacción se inicie, no se puede continuar porque el valor inicial que tenía el dato para la transacción ha cambiado. Este mecanismo asegura la seriabilidad al ordenar las transacciones evitando solapamientos, basándose en el momento de inicio de cada transacción. Además, no se pueden producir interbloqueos al no usar mecanismos que impliquen la espera de las transacciones. El administrador de transacciones asigna también una estampa de tiempo a todas las operaciones solicitadas por una transacción. Más aún, a cada elemento de datos x se le asigna una estampa de tiempo de escritura, wts(x), y una estampa de tiempo de lectura, rts(x); sus valores indican la estampa de tiempo más grande para cualquier lectura y escritura de x, respectivamente.
ejemplo didactico de esta tecnica:
Para  ordenar  las  estampas de tiempo (TO) se realizara mediante la siguiente regla basadas en el lenguaje de programación turbo pascal.
Regla TO: dadas dos operaciones en conflicto,  Oij y Okl, perteneciendo a las transacciones Ti y Tk, respectivamente, Oij  es ejecutada antes de Okl, si y solamente si, ts(Ti) < ts(Tk). En este caso Ti se dice ser un transacción más vieja Tk se dice ser una transacción más joven.
Dado este orden, un conflicto entre operaciones se puede resolver de la siguiente forma:
for Ri(x) do beginif ts(Ti) < wts( x ) then
reject Ri(x)
else
accept Ri(x)
rts(x) ð ts(Ti)
end
for Wi(x) do beginif ts(Ti) < rts(x) and
ts(Ti) < wts(x) then
reject Wi(x)
else
accept Wi(x)
wts(x) ð ts(Ti)
end
La acción de rechazar una operación, significa que la transacción que la envió necesita reiniciarse para obtener la estampa de tiempo más reciente del dato e intentar hacer nuevamente la operación sobre el dato.

TECNICAS DE BLOQUEO

 

Los bloqueos como solución al problema de la concurrencia
Una forma de controlar la concurrencia es hacer que cada transacción deba adquirir un derecho de acceso exclusivo a cada fragmento de datos que necesite modificar. A estos “derechos” se les denomina bloqueos.
Bloqueo binario
La forma más simple de bloquear es utilizar bloqueos binarios. En un bloqueo binario, cada transacción debe solicitar el bloqueo de cada fragmento de datos A que vaya a utilizar antes de acceder a él (sea para leerlo o escribirlo), mediante una operación bloquear(A). Deberá liberar todos los bloqueos, mediante una operacióndesbloquear(A) de modo que otras tareas puedan tomarlos.
Este sistema de bloqueos tiene una implementación muy simple, ya que solo requiere mantener una tabla que indica qué partes de los datos está bloqueada y por qué transacción.
Bloqueos de lectura y escritura
El sistema de bloqueos binarios es simple pero demasiado restrictivo, ya que no permite que dos transacciones que van a leer el mismo fragmento de datos A lo hagan simultáneamente, cuando en realidad, no puede haber problemas en varios lectores simultáneos. Los bloqueos de lectura/escritura hacen más débil la restricción permitiendo la siguiente compatibilidad de bloqueos.
TABLALECTURAESCRITURA
LECTURACompatibleIncompatible
ESCRITURAIncompatibleIncompatible
En este caso, las operaciones que las transacciones deben realizar son tres: desbloquear(A) ybloquear_para_lectura(A) o bloquear_para_escritura(A).
Nótese que esas llamadas se implementan de diferentes formas en diferentes gestores de bases de datos. Por ejemplo, en MySQL, tanto las solicitudes de bloqueos como las liberaciones se realizan mediante una sola llamada del API de los gestores de almacenamiento:
store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type)
Cada llamada a store_lock utiliza el manejador de una tabla thd concreta, y se indica la información de los datos a bloquear mediante la variable to, y el tipo de bloqueo mediante lock_type (el número de tipos definidos en MySQL es muy grande, ya que cubre todos los tipos de bloqueo que implementan los múltiples gestores de almacenamiento disponibles).
serializacion de los bloqueos de lectura/escritura
La serialización de las operaciones de lectura y escritura consiste en ordenar esas operaciones para un conjunto de transacciones concurrentes de modo que los resultados de las operaciones sean correctos. Por ejemplo, si tenemos las siguientes transacciones X e Y, puede darse la siguiente situación.