En bases de datos y procesamiento de transacciones (gestión de transacciones), el aislamiento de instantáneas es una garantía de que todas las lecturas realizadas en una transacción verán una instantánea consistente de la base de datos (en la práctica, lee los últimos valores confirmados que existían en el momento en que comenzó), y la transacción en sí se confirmará exitosamente solo si ninguna actualización que haya realizado entra en conflicto con cualquier actualización simultánea realizada desde esa instantánea.
El aislamiento de instantáneas ha sido adoptado por varios sistemas de gestión de bases de datos importantes , como InterBase , Firebird , Oracle , MySQL , [1] PostgreSQL , SQL Anywhere , MongoDB [2] y Microsoft SQL Server (2005 y posteriores). La razón principal para su adopción es que permite un mejor rendimiento que la serialización , pero aún evita la mayoría de las anomalías de concurrencia que la serialización evita (pero no todas). En la práctica, el aislamiento de instantáneas se implementa dentro del control de concurrencia de múltiples versiones (MVCC), donde se mantienen los valores generacionales de cada elemento de datos (versiones): MVCC es una forma común de aumentar la concurrencia y el rendimiento al generar una nueva versión de un objeto de base de datos cada vez que se escribe el objeto y permitir las operaciones de lectura de transacciones de varias últimas versiones relevantes (de cada objeto). El aislamiento de instantáneas se ha utilizado [3] para criticar la definición de niveles de aislamiento del estándar ANSI SQL -92 , ya que no presenta ninguna de las "anomalías" que prohibía el estándar SQL, pero no es serializable (el nivel de aislamiento libre de anomalías definido por ANSI).
A pesar de su distinción con la serializabilidad, Oracle a veces se refiere al aislamiento de instantáneas como serializable .
Una transacción que se ejecuta con aislamiento de instantáneas parece operar en una instantánea personal de la base de datos, tomada al comienzo de la transacción. Cuando la transacción concluye, se confirmará correctamente solo si los valores actualizados por la transacción no se han modificado externamente desde que se tomó la instantánea. Un conflicto de escritura a escritura de este tipo hará que la transacción se cancele.
En una anomalía de sesgo de escritura , dos transacciones (T1 y T2) leen simultáneamente un conjunto de datos superpuestos (por ejemplo, los valores V1 y V2), realizan simultáneamente actualizaciones disjuntas (por ejemplo, T1 actualiza V1, T2 actualiza V2) y, finalmente, confirman simultáneamente, sin que ninguna haya visto la actualización realizada por la otra. Si el sistema fuera serializable, tal anomalía sería imposible, ya que T1 o T2 tendrían que ocurrir "primero" y ser visibles para la otra. Por el contrario, el aislamiento de instantáneas permite anomalías de sesgo de escritura.
Como ejemplo concreto, imaginemos que V1 y V2 son dos saldos que tiene una sola persona, Phil. El banco permitirá que V1 o V2 tengan un déficit, siempre que el total de ambos nunca sea negativo (es decir, V1 + V2 ≥ 0). Ambos saldos son actualmente de $100. Phil inicia dos transacciones simultáneamente: T1 retira $200 de V1 y T2 retira $200 de V2.
Si la base de datos garantiza transacciones serializables, la forma más sencilla de codificar T1 es deducir $200 de V1 y luego verificar que V1 + V2 ≥ 0 todavía se cumple, abortando si no. T2 de manera similar deduce $200 de V2 y luego verifica V1 + V2 ≥ 0. Dado que las transacciones deben serializarse, o T1 ocurre primero, dejando V1 = −$100, V2 = $100 y evitando que T2 tenga éxito (ya que V1 + (V2 − $200) ahora es −$200), o T2 ocurre primero y de manera similar evita que T1 se confirme.
Sin embargo, si la base de datos está bajo aislamiento de instantáneas (MVCC), T1 y T2 operan en instantáneas privadas de la base de datos: cada una deduce $200 de una cuenta y luego verifica que el nuevo total sea cero, utilizando el valor de la otra cuenta que se encontraba cuando se tomó la instantánea. Dado que ninguna actualización entra en conflicto, ambas se confirman correctamente, lo que deja V1 = V2 = −$100 y V1 + V2 = −$200.
Algunos sistemas creados con control de concurrencia multiversión (MVCC) pueden admitir (solamente) aislamiento de instantáneas para permitir que las transacciones continúen sin preocuparse por las operaciones concurrentes y, lo que es más importante, sin necesidad de volver a verificar todas las operaciones de lectura cuando la transacción finalmente se confirma. Esto es conveniente porque MVCC mantiene una serie de estados consistentes con el historial reciente. La única información que se debe almacenar durante la transacción es una lista de actualizaciones realizadas, que se puede escanear en busca de conflictos con bastante facilidad antes de confirmarse. Sin embargo, los sistemas MVCC (como MarkLogic) utilizarán bloqueos para serializar las escrituras junto con MVCC para obtener algunas de las ganancias de rendimiento y aún admitir el nivel de aislamiento de "serialización" más fuerte.
Los posibles problemas de inconsistencia que surgen de anomalías de sesgo de escritura se pueden solucionar agregando actualizaciones (de otro modo innecesarias) a las transacciones para aplicar la propiedad de serialización . [4] [5] [6] [7]
En el ejemplo anterior, podemos materializar el conflicto agregando una nueva tabla que haga explícita la restricción oculta y asigne a cada persona su saldo total . Phil comenzaría con un saldo total de $200 y cada transacción intentaría restarle $200, lo que crearía un conflicto de escritura-escritura que evitaría que las dos se realicen simultáneamente. Sin embargo, este enfoque viola la forma normal .
Como alternativa, podemos convertir una de las lecturas de la transacción en una escritura. Por ejemplo, T2 podría establecer V1 = V1, lo que crearía un conflicto de escritura-escritura artificial con T1 y, nuevamente, evitaría que las dos operaciones se realicen con éxito simultáneamente. Esta solución puede no ser siempre posible.
En general, por lo tanto, el aislamiento de instantáneas traslada parte del problema de mantener restricciones no triviales al usuario, que puede no apreciar ni los posibles inconvenientes ni las posibles soluciones. La ventaja de esta transferencia es un mejor rendimiento.
El aislamiento de instantáneas se denomina modo "serializable" en Oracle [8] [9] [10] y en versiones de PostgreSQL anteriores a 9.1, [11] [12] [13] , lo que puede causar confusión con el modo de " serialización real ". Existen argumentos tanto a favor como en contra de esta decisión; lo que está claro es que los usuarios deben ser conscientes de la distinción para evitar posibles comportamientos anómalos no deseados en la lógica de su sistema de base de datos.
El aislamiento de instantáneas surgió del trabajo sobre bases de datos de control de concurrencia de múltiples versiones , donde se mantienen múltiples versiones de la base de datos simultáneamente para permitir que los lectores se ejecuten sin colisionar con los escritores. Un sistema de este tipo permite una definición e implementación naturales de dicho nivel de aislamiento. [3] Se reconoció que InterBase , posteriormente propiedad de Borland , proporcionaba SI en lugar de serialización completa en la versión 4, [3] y probablemente permitía anomalías de sesgo de escritura desde su primer lanzamiento en 1985. [14]
Lamentablemente, el estándar ANSI SQL-92 se escribió teniendo en mente una base de datos basada en bloqueos y, por lo tanto, es bastante vago cuando se aplica a los sistemas MVCC. Berenson et al. escribieron un artículo en 1995 [3] criticando el estándar SQL y citaron el aislamiento de instantáneas como un ejemplo de un nivel de aislamiento que no exhibía las anomalías estándar descritas en el estándar ANSI SQL-92, pero que aún tenía un comportamiento anómalo cuando se lo comparaba con las transacciones serializables .
En 2008, Cahill et al. demostraron que las anomalías de sesgo de escritura se podían prevenir detectando y cancelando tripletes "peligrosos" de transacciones concurrentes. [15] Esta implementación de serializabilidad es adecuada para bases de datos de control de concurrencia de múltiples versiones y se adoptó en PostgreSQL 9.1, [12] [13] [16] donde se la conoce como Aislamiento de instantáneas serializable (SSI). Cuando se usa de manera consistente, esto elimina la necesidad de las soluciones alternativas anteriores. La desventaja del aislamiento de instantáneas es un aumento en las transacciones canceladas. Esto puede funcionar mejor o peor que el aislamiento de instantáneas con las soluciones alternativas anteriores, según la carga de trabajo.