Diferencia entre "lectura confirmada" y "lectura repetible" en SQL Server

Resuelto Fore asked hace 14 años • 9 respuestas

Creo que los niveles de aislamiento anteriores son muy parecidos. ¿Podría alguien describir con algunos buenos ejemplos cuál es la principal diferencia?

Fore avatar Oct 27 '10 22:10 Fore
Aceptado

La lectura confirmada es un nivel de aislamiento que garantiza que se lea cualquier dato leído que se haya confirmado en ese momento. Simplemente impide que el lector vea cualquier lectura intermedia, no comprometida y "sucia". No hace ninguna promesa de que si la transacción vuelve a emitir la lectura, encontrará los mismos datos, los datos se pueden cambiar libremente después de la lectura.

La lectura repetible es un nivel de aislamiento más alto, que además de las garantías del nivel de lectura comprometida, también garantiza que cualquier dato leído no pueda cambiar , si la transacción vuelve a leer los mismos datos, encontrará los datos leídos anteriormente en su lugar, sin cambios. y disponible para leer.

El siguiente nivel de aislamiento, serializable, ofrece una garantía aún más sólida: además de todo lo que garantiza la lectura repetible, también garantiza que no se puedan ver datos nuevos en una lectura posterior.

Digamos que tiene una tabla T con una columna C con una fila, digamos que tiene el valor '1'. Y considera que tienes una tarea simple como la siguiente:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

Se trata de una tarea sencilla que emite dos lecturas de la tabla T, con un retraso de 1 minuto entre ellas.

  • en LEER COMPROMETIDO, el segundo SELECT puede devolver cualquier dato. Una transacción simultánea puede actualizar el registro, eliminarlo o insertar nuevos registros. La segunda selección siempre verá los nuevos datos.
  • en LECTURA REPETIBLE, se garantiza que el segundo SELECT mostrará al menos las filas que se devolvieron desde el primer SELECT sin cambios . Se pueden agregar nuevas filas mediante una transacción simultánea en ese minuto, pero las filas existentes no se pueden eliminar ni cambiar.
  • en SERIALIZABLE se lee que se garantiza que la segunda selección verá exactamente las mismas filas que la primera. Ninguna fila puede cambiar, ni eliminarse, ni se pueden insertar nuevas filas mediante una transacción concurrente.

Si sigue la lógica anterior, podrá darse cuenta rápidamente de que las transacciones SERIALIZABLES, si bien pueden facilitarle la vida, siempre bloquean por completo todas las posibles operaciones concurrentes, ya que requieren que nadie pueda modificar, eliminar ni insertar ninguna fila. El nivel de aislamiento de transacciones predeterminado del System.Transactionsalcance .Net es serializable, y esto generalmente explica el pésimo rendimiento resultante.

Y por último, también está el nivel de aislamiento SNAPSHOT. El nivel de aislamiento SNAPSHOT ofrece las mismas garantías que el serializable, pero no exige que ninguna transacción concurrente pueda modificar los datos. Más bien, obliga a cada lector a ver su propia versión del mundo (su propia "instantánea"). Esto hace que sea muy fácil de programar y muy escalable, ya que no bloquea las actualizaciones simultáneas. Sin embargo, ese beneficio tiene un precio: consumo adicional de recursos del servidor.

Lecturas complementarias:

  • Niveles de aislamiento en el motor de base de datos
  • Efectos de concurrencia
  • Elegir niveles de aislamiento basados ​​en versiones de filas
Remus Rusanu avatar Oct 27 '2010 17:10 Remus Rusanu

Lectura repetible

El estado de la base de datos se mantiene desde el inicio de la transacción. Si recupera un valor en la sesión1, luego actualiza ese valor en la sesión2, recuperarlo nuevamente en la sesión1 arrojará los mismos resultados. Las lecturas son repetibles.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Leer comprometido

Dentro del contexto de una transacción, siempre recuperará el valor confirmado más reciente. Si recupera un valor en la sesión1, lo actualiza en la sesión2 y luego lo recupera en la sesión1 nuevamente, obtendrá el valor modificado en la sesión2. Lee la última fila comprometida.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

¿Tiene sentido?

Hazel_arun avatar Jan 18 '2013 07:01 Hazel_arun