Aislamiento (ACID)En bases de datos, el aislamiento es una propiedad que define cómo y cuándo los cambios producidos por una operación se hacen visibles para las demás operaciones concurrentes. Aislamiento es una de las 4 propiedades ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad) aplicables a una base de datos transaccional. Niveles de aislamientoDe las cuatro propiedades ACID de un Sistema de gestión de bases de datos relacionales (SGBDR) la de aislamiento es la que más frecuentemente se relaja. Para obtener el mayor nivel de aislamiento, un SGBDR generalmente hace un bloqueo de los datos o implementa un Control de concurrencia mediante versiones múltiples (MVCC), lo que puede resultar en una pérdida de concurrencia. Por ello se necesita añadir lógica adicional al programa que accede a los datos para su funcionamiento correcto. La mayor parte de los SGBDR ofrecen unos ciertos niveles de aislamiento que controlan el grado de bloqueo durante el acceso a los datos. Para la mayor parte de aplicaciones, el acceso a los datos se puede realizar de modo que se eviten altos niveles de aislamiento (i.e. nivel SERIALIZABLE), reduciendo así la sobrecarga debida a la necesidad de bloqueos por el sistema. El programador debe analizar detenidamente el código que accede a la base de datos para asegurarse de que el descenso del nivel de aislamiento que ofrece el SGBD no produce errores en el programa. Recíprocamente, si se usan altos niveles de aislamiento la posibilidad de bloqueo aumenta, lo que también requiere análisis cuidadoso del código. Los niveles de aislamiento están definidos por ANSI/ISO SQL, y se listan a continuación. SerializableEste es el nivel de aislamiento más alto. Especifica que todas las transacciones ocurran de modo aislado, o dicho de otro modo, como si todas las transacciones se ejecutaran de modo serie (una tras otra). La sensación de ejecución simultánea de dos o más transacciones que perciben los usuarios sería una ilusión producida por el SGBD. Si el SGBDR hace una implementación basada en bloqueos, la serialización requiere que los bloques de lectura y escritura se liberen al final de la transacción. Del mismo modo deben realizarse bloqueos de rango -sobre los datos seleccionados con SELECT usando WHERE- para evitar el efecto de las lecturas fantasma (ver más abajo). Cuando se hace una implementación no basada en bloqueos, si el SGBDR detecta una colisión de escritura entre transacciones solo a una de ellas se le autoriza cometer. Lecturas repetibles (Repeatable reads)En este nivel de aislamiento, un SGBDR que implemente el control de concurrencia basado en bloqueos mantiene los bloqueos de lectura y escritura -de los datos seleccionados- hasta el final de la transacción. Sin embargo, no se gestionan los bloqueos de rango, por lo que las lecturas fantasma pueden ocurrir (ver más abajo). Lecturas comprometidas (Read committed)En este nivel de aislamiento, un SGBDR que implemente el control de concurrencia basado en bloqueos mantiene los bloqueos de escritura -de los datos seleccionados- hasta el final de la transacción, mientras que los bloqueos de lectura se cancelan tan pronto como acaba la operación de SELECT (por lo que el efecto de las lecturas no repetibles puede ocurrir, como se explica más abajo). Al igual ocurría en el nivel anterior, no se gestionan los bloqueos de rango. Lecturas no comprometidas (Read uncommitted)Este es el menor nivel de aislamiento. En él se permiten las lecturas sucias (ver más abajo), por lo que una transacción puede ver cambios no cometidos aún por otra transacción. Nivel de aislamiento por defectoEl nivel de aislamiento por defecto de distintos SGBDR varía ampliamente. La mayoría de bases de datos que gestionan transacciones permiten al usuario establecer cualquier nivel de aislamiento. Algunos SGBDR requieren sintaxis especial cuando se realiza una operación SELECT que efectúa bloqueos (e.g. SELECT ... FOR UPDATE para bloquear para escritura aquellas filas accedidas). Sin embargo, la definición anterior ha sido criticada en el artículo A Critique of ANSI SQL Isolation Levels por ambigua, y por no reflejar de modo preciso el aislamiento proporcionado por muchas bases de datos:
Hay también otras críticas sobre las definiciones de aislamiento SQL de ANSI, en cuanto a que incita a los implementadores a realizar "trabajos sucios":
Efectos en lecturaEl estándar ANSI/ISO SQL 92 se refiere a tres efectos de lectura diferentes cuando la transacción 1 lee datos que podría haber cambiado la transacción 2. En los siguientes ejemplos se ejecutan dos transacciones. La primera ejecuta la consulta 1. Entonces una segunda transacción ejecuta la consulta 2 y la comete. Por último, la primera transacción ejecuta la consulta 1 de nuevo. Las consultas usan esta tabla:
Lecturas suciasUna lectura sucia ocurre cuando se le permite a una transacción la lectura de una fila que ha sido modificada por otra transacción concurrente pero todavía no ha sido cometida. Las lecturas sucias funcionan de modo similar a las lecturas no repetibles; sin embargo la segunda transacción no necesita ser cometida para que la primera dé un resultado diferente. Lo único que se puede prevenir en el nivel de aislamiento LECTURAS NO COMETIDAS es que las actualizaciones aparezcan en desorden en el resultado; esto es, que las primeras actualizaciones siempre aparecerán antes que las actualizaciones posteriores. En el ejemplo, la transacción 2 cambia una fila, pero no comete los cambios. La transacción 1 entonces lee los datos sin cometer. Si ahora la transacción 2 deshace sus cambios (ya leídos por la transacción 1) o realiza otros cambios, entonces los datos que ha recuperado la transacción 1 serán erróneos.
Pero no existe ningún usuario que tenga la edad de 21, pues la Transacción 2 nunca cometió los cambios. Lecturas no repetiblesUna lectura no repetible ocurre cuando en el curso de una transacción una fila se lee dos veces y los valores no coinciden. El efecto de lecturas no repetible puede ocurrir en una implementación de concurrencia mediante bloqueos cuando no se efectúan éstos al hacer un SELECT, o cuando los bloqueos se liberan nada más terminar la operación SELECT. Cuando se usa el método MVCC, las lecturas no repetibles pueden aparecer cuando se relaja el requisito de que al cometer una transacción afectada por un conflicto esta deba deshacerse.
En este ejemplo, la transacción 2 comete correctamente, lo que significa que sus cambios a la fila con id 1 deberían hacerse visibles. Sin embargo, la transacción 1 ya ha leído un valor distinto para edad en esa fila. En los niveles de aislamiento SERIALIZABLE y REPEATABLE READ, el SGBDR debería devolver el valor antiguo. En los niveles READ COMMITTED y READ UNCOMMITTED, el SGBDR debería devolver el valor nuevo; esto es una lectura no repetible. Hay dos estrategias básicas para prevenir las lecturas no repetibles. La primera consiste en retrasar la ejecución de la transacción 2 hasta que la transacción 1 haya cometido o haya deshecho. Este método se usa con bloqueos, y es equivalente a la ejecución en serie T1, T2. La ejecución en serie no muestra efectos de lecturas no repetibles. La otra estrategia, la usada en MVCC, se permite cometer a la transacción 2 primero, lo que permite mejor concurrencia. Si embargo, la transacción 1, que comenzó antes que la transacción 2, debe continuar operando sobre una versión anterior de la base de datos —una instantánea del momento en que empezó. Cuando la transacción 1 intenta cometer, el SGBDR verifica si el resultado de cometer la transacción 1 sería equivalente a la ejecución serie T1, T2. Si fuera así la transacción 1 podría proceder. Si no fuera así, la transacción 1 fallaría y debería deshacerse. Usando control de concurencia mediante bloqueos, al nivel de aislamiento REPEATABLE READ, la fila con id 1 debería bloquearse, bloqueando de ese modo la consulta 2 hasta que la transacción 1 se cometa o deshaga. En el modo READ COMMITTED, la segunda vez que se ejecute la consulta 1, la edad habrá cambiado. Usando MVCC, al nivel de aislamiento SERIALIZABLE, ambas consultas SELECT ven una instantánea de la base de datos tomada al comienzo de la transacción 1. Por ello devuelven los mismo datos. Sin embargo, si la transacción 1 intenta entonces actualizar esa misma fila, ocurriría un fallo de serialización y la transacción 1 estaría forzada a deshacerse. Al nivel de aislamiento READ COMMITTED, cada consulta ve una instantánea de la base de datos tomada al principio de la consulta. Por ello, cada una ve datos distintos en la fila actualizada. No puede producirse fallo de serialización en este modo (ya que no se hace promesa de serializabilidad), y la transacción 1 no deberá reintentarse. Lecturas fantasmaUna lectura fantasma ocurre cuando, durante una transacción, se ejecutan dos consultas idénticas, y los resultados de la segunda no son iguales a los de la primera. Esto puede ocurrir cuando no se realizan bloqueos de rango al realizar una operación SELECT ... WHERE. La anomalía de las lecturas fantasma es una caso particular de las lecturas no repetibles cuando la transacción 1 repite una consulta acotada en rango SELECT ... WHERE y, entre ambas operaciones la transacción 2 crea (i.e. INSERT) nuevas filas (en la misma tabla) que entran dentro de esa cláusula WHERE.
Nótese que la transacción 1 ejecuta la misma consulta dos veces. Si se mantuviera el mayor nivel de aislamiento, los resultados de ambas consultas coincidirían (QUE ES LO QUE SUCEDE), de hecho es lo que se pide a una base de datos operando al nivel de aislamiento SERIALIZABLE. Sin embargo, a niveles de aislamiento menores, pueden obtenerse resultados distintos. Al nivel de aislamiento SERIALIZABLE, la consulta 1 bloquearía todos los registros con edades comprendidas entre 10 y 30, de modo que la consulta 2 quedaría bloqueada hasta que se cometiera la transacción 1. En modo REPEATABLE READ, el rango de 10 a 30 no se bloquearía, permitiendo la inserción de modo que la segunda ejecución de la consulta 1 sí incluirá la nueva fila en sus resultados. Niveles de aislamiento, efectos de lectura y bloqueosNiveles de aislamiento vs Efectos de lectura
"puede ocurrir" significa que el nivel de aislamiento sufre ese efecto, mientras que "-" significa que no lo sufre. Niveles de aislamiento vs Bloqueos
"V" indica que el método bloquea esa operación, manteniéndolo hasta el final de la transacción. Nota: Las operaciones de lectura (i.e. SELECT) pueden efectuar bloqueos (compartidos) en el nivel Read Committed, pero se liberan inmediatamente tras la operación de lectura. Véase tambiénReferencias
|