lectura - niveles de aislamiento mysql
Diferencia entre lectura confirmada y lectura repetible (6)
Creo que los niveles de aislamiento anteriores son muy parecidos. ¿Podría alguien describir por favor con algunos buenos ejemplos cuál es la principal diferencia?
Lectura repetible
El estado de la base de datos se mantiene desde el inicio de la transacción. Si recupera un valor en session1, luego actualice ese valor en session2, recuperarlo nuevamente en session1 devolverá 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 comprometido más recientemente. Si recupera un valor en session1, lo actualiza en session2, luego lo recupera en session1again, obtendrá el valor modificado en session2. 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?
Intentando explicar esta duda con diagramas simples.
Read Committed: aquí en este nivel de aislamiento, la Transacción T1 leerá el valor actualizado de la X cometida por la Transacción T2.
Lectura repetible: en este nivel de aislamiento, la Transacción T1 no tendrá en cuenta los cambios cometidos por la Transacción T2.
Mi observación sobre la solución inicial aceptada.
En RR (mysql predeterminado): si un tx está abierto y se ha activado un SELECT, otro tx NO puede eliminar ninguna fila perteneciente al conjunto de resultados LEER anterior hasta que se haya confirmado el tx anterior (de hecho, la sentencia de eliminación en el nuevo tx simplemente se bloqueará) Sin embargo, el próximo tx puede eliminar todas las filas de la tabla sin ningún problema. Por cierto, un próximo READ en tx anterior seguirá viendo los datos antiguos hasta que se confirme.
Read committed es un nivel de aislamiento que garantiza que cualquier lectura de datos que se haya confirmado en el momento se lea. Simplemente restringe al lector de ver cualquier lectura intermedia, no comprometida y "sucia". No hace ninguna promesa de que si la transacción reemite la lectura, encontrará los mismos datos, los datos son libres de cambiar después de su lectura.
La lectura repetible es un nivel de aislamiento superior, que además de las garantías del nivel de lectura confirmada, también garantiza que cualquier lectura de datos no puede cambiar , si la transacción vuelve a leer los mismos datos, encontrará los datos previamente leídos en su lugar, sin cambios y disponible para leer
El siguiente nivel de aislamiento, serializable, ofrece una garantía aún mayor: además de todas las garantías de lectura repetibles, también garantiza que no se puedan ver datos nuevos en una lectura posterior.
Supongamos que tiene una tabla T con una columna C con una fila, digamos que tiene el valor ''1''. Y considere que tiene una tarea sencilla como la siguiente:
BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY ''00:01:00''
SELECT * FROM T;
COMMIT;
Esa es una tarea simple que emite dos lecturas de la tabla T, con un retraso de 1 minuto entre ellas.
- bajo LEER COMITTED, el segundo SELECT puede devolver cualquier dato. Una transacción simultánea puede actualizar el registro, eliminarlo, insertar nuevos registros. La segunda selección siempre verá los nuevos datos.
- en LECTURA REPETIBLE, el segundo SELECCIONAR está garantizado para ver las filas que se han visto al principio seleccionar sin cambios . Se pueden agregar nuevas filas mediante una transacción concurrente en ese minuto, pero las filas existentes no se pueden eliminar ni cambiar.
- bajo SERIALIZABLE lee, la segunda selección garantiza que se ven exactamente las mismas filas que la primera. Ninguna fila puede cambiar, ni eliminarse, ni se pueden insertar nuevas filas mediante una transacción simultánea.
Si sigue la lógica anterior, puede darse cuenta rápidamente de que las transacciones SERIALIZABLES, si bien le pueden facilitar la vida, siempre bloquean por completo todas las operaciones simultáneas posibles, ya que requieren que nadie pueda modificar, eliminar ni insertar ninguna fila. El nivel de aislamiento de la transacción por defecto del alcance de .Net System.Transactions
es serializable, y esto generalmente explica el desempeño abismal que resulta.
Y finalmente, también está el nivel de aislamiento SNAPSHOT. El nivel de aislamiento de SNAPSHOT ofrece las mismas garantías que la serialización, pero no al requerir que ninguna transacción simultánea pueda modificar los datos, sino al hacer que cada lector vea su propia versión del mundo (su propia "instantánea"). Esto hace que sea muy fácil programar en contra, muy escalable, ya que no bloquea las actualizaciones simultáneas, pero, por supuesto, tiene un precio, y el precio es el consumo de recursos adicionales del servidor.
Lecturas suplementarias:
Simplemente la respuesta de acuerdo con mi lectura y comprensión de este hilo y la respuesta @ remus-rusanu se basa en este simple escenario:
Hay dos procesos A y B. El proceso B está leyendo. Tabla X. El proceso A está escribiendo en la tabla X. El proceso B está leyendo nuevamente la Tabla X.
- ReadUncommitted : el proceso B puede leer datos no confirmados del proceso A y podría ver diferentes filas basadas en la escritura B. Sin bloqueo en absoluto
- ReadCommitted : El Proceso B puede leer SÓLO datos confirmados del proceso A y podría ver diferentes filas basadas en la escritura B COMPROMETIDA solamente. podríamos llamarlo bloqueo simple?
- RepeatableRead : El proceso B leerá los mismos datos (filas) que el proceso A. Pero el proceso A puede cambiar otras filas. Nivel de filas Bloque
- Serializable : El proceso B leerá las mismas filas que antes y el proceso A no podrá leer o escribir en la tabla. Bloque a nivel de tabla
- Instantánea : cada proceso tiene su propia copia y están trabajando en ello. Cada uno tiene su propia vista
Una pregunta anterior que ya tiene una respuesta aceptada, pero me gusta pensar en estos dos niveles de aislamiento en términos de cómo cambian el comportamiento de bloqueo en SQL Server. Esto podría ser útil para aquellos que están depurando deadlocks como yo.
LEER COMPROMETIDO (predeterminado)
Los bloqueos compartidos se toman en SELECT y luego se liberan cuando se completa la instrucción SELECT . Así es como el sistema puede garantizar que no haya lecturas sucias de datos no confirmados. Otras transacciones aún pueden cambiar las filas subyacentes después de que se complete su SELECCIÓN y antes de que se complete su transacción.
LEÍDO REPETIBLE
Los bloqueos compartidos se toman en SELECT y luego se liberan solo después de que se completa la transacción . Así es como el sistema puede garantizar que los valores que lea no cambien durante la transacción (porque permanecen bloqueados hasta que finaliza la transacción).