¿Cuál es la diferencia entre lectura no repetible y lectura fantasma?


154

¿Cuál es la diferencia entre lectura no repetible y lectura fantasma?

He leído el artículo de Aislamiento (sistemas de bases de datos) de Wikipedia , pero tengo algunas dudas. En el siguiente ejemplo, ¿qué sucederá: la lectura no repetible y la lectura fantasma ?

Transacción A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
SALIDA:
1----MIKE------29019892---------5000
Transacción B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
Transacción A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

Otra duda es, en el ejemplo anterior, ¿qué nivel de aislamiento debe usarse? ¿Y por qué?


Respuestas:


165

De Wikipedia (que tiene ejemplos excelentes y detallados para esto):

Se produce una lectura no repetible, cuando durante el curso de una transacción, se recupera una fila dos veces y los valores dentro de la fila difieren entre las lecturas.

y

Una lectura fantasma ocurre cuando, en el curso de una transacción, se ejecutan dos consultas idénticas, y la colección de filas devueltas por la segunda consulta es diferente de la primera.

Ejemplos simples:

  • El usuario A ejecuta la misma consulta dos veces.
  • En el medio, el usuario B ejecuta una transacción y se compromete.
  • Lectura no repetible: la fila A que el usuario A ha consultado tiene un valor diferente la segunda vez.
  • Lectura fantasma: todas las filas de la consulta tienen el mismo valor antes y después, pero se seleccionan diferentes filas (porque B ha eliminado o insertado algunas). Ejemplo: select sum(x) from table;devolverá un resultado diferente incluso si ninguna de las filas afectadas se ha actualizado, si se han agregado o eliminado filas.

En el ejemplo anterior, ¿qué nivel de aislamiento se utilizará?

El nivel de aislamiento que necesita depende de su aplicación. Hay un alto costo para un "mejor" nivel de aislamiento (como la concurrencia reducida).

En su ejemplo, no tendrá una lectura fantasma, porque selecciona solo de una sola fila (identificada por la clave primaria). Puede tener lecturas no repetibles, por lo que si eso es un problema, es posible que desee tener un nivel de aislamiento que lo impida. En Oracle, la transacción A también podría emitir un SELECCIONAR PARA ACTUALIZAR, luego la transacción B no puede cambiar la fila hasta que A haya terminado.


66
Realmente no entiendo la lógica de una sintaxis tal ... A no repetibles de lectura se produce cuando se la lectura repetida (y obtiene un valor diferente) ?? ...!
serhio

14
@serhio "no repetible" se refiere al hecho de que puede leer un valor una vez y obtener x como resultado, y luego leer de nuevo y obtener y como resultado, por lo que no puede repetir (no repetible) los mismos resultados de dos consultas separadas de la misma fila, porque ese valor de fila se actualizó entre lecturas.
BateTech

@Thilo ¿Algún ejemplo de caso de uso real en el que la lectura repetible pueda crear problemas y donde sea necesario?
user104309

¿Qué pasa si el PK se modifica en otra transacción? ¿Podría eso resultar en una lectura fantasma? (Una cosa extraña que hacer en la mayoría de los casos, pero no imposible).
jpmc26

1
Ambos suenan igual para mí
sn.anurag

125

Una forma simple en la que me gusta pensar es:

Tanto las lecturas no repetibles como las fantasmas tienen que ver con las operaciones de modificación de datos de una transacción diferente, que se confirmaron después de que comenzó su transacción, y luego fueron leídas por su transacción.

Las lecturas no repetibles son cuando su transacción lee ACTUALIZACIONES confirmadas de otra transacción. La misma fila ahora tiene valores diferentes a los que tenía cuando comenzó su transacción.

Las lecturas fantasmas son similares, pero cuando se leen de INSERTOS y / o BORRADOS comprometidos de otra transacción. Hay nuevas filas o filas que han desaparecido desde que comenzó la transacción.

Las lecturas sucias son similares a las lecturas no repetibles y fantasmas, pero se relacionan con la lectura de datos NO COMPROMETIDOS, y ocurren cuando se lee una ACTUALIZACIÓN, INSERCIÓN o ELIMINACIÓN de otra transacción, y la otra transacción aún NO ha confirmado los datos. Está leyendo datos "en progreso", que pueden no estar completos y que en realidad nunca se pueden confirmar.


44
Tiene que ver con niveles de aislamiento de transacciones y concurrencia. Con el nivel de aislamiento predeterminado, no obtendrá lecturas sucias y, en la mayoría de los casos, querrá evitar lecturas sucias. Hay niveles de aislamiento o sugerencias de consulta que permitirán lecturas sucias, lo que en algunos casos es una compensación aceptable para lograr una mayor concurrencia o es necesario debido a un caso límite, como la solución de problemas de una transacción en curso desde otra conexión. Es bueno que la idea de una lectura sucia no pase la "prueba de olor" para usted, porque como regla general, deben evitarse, pero tienen un propósito.
BateTech

1
@PHPAvenger aquí es un caso de uso para el nivel de aislamiento READ UNCOMMITTED: siempre existe la posibilidad de encontrar un punto muerto entre una consulta de selección y una de actualización (explicado aquí ). Si la consulta de selección es demasiado compleja para crear un índice de cobertura, para evitar puntos muertos, querrá usar un nivel de aislamiento LEER NO COMPROMISO con el riesgo de encontrar lecturas sucias, pero con qué frecuencia revierte las transacciones para preocuparse por esas lecturas sucias no siendo permanente?
petrica.martinescu

1
@ petrica.martinescu los problemas causados ​​por lecturas sucias NO son solo acerca de si una transacción se revierte o no. Las lecturas sucias pueden devolver resultados muy inexactos dependiendo de cómo se hayan modificado los datos en las transacciones pendientes. Imagine una transacción que realiza una serie de varias eliminaciones, actualizaciones y / o inserciones. Si lee los datos en el medio de esa transacción usando "lectura no confirmada", está incompleta. El nivel de aislamiento de instantáneas (en SQL Server) es una alternativa mucho mejor para leer sin confirmar. Un caso de uso válido para leer el nivel de aislamiento no confirmado en un sistema de producción es una OMI rara.
BateTech

2
@DiponRoy gran pregunta. El bloqueo implementado si se usa aislamiento de lectura repetible (RR) debe evitar que se produzcan eliminaciones en las filas que se han seleccionado. He visto diferentes definiciones de los 2 niveles iso a lo largo de los años, principalmente diciendo que fantasma es un cambio en la colección / # filas devueltas y RR es la misma fila que se está cambiando. Acabo de comprobar que la documentación actualizada de MS SQL dice que las eliminaciones pueden causar no RR ( docs.microsoft.com/en-us/sql/odbc/reference/develop-app/… ), así que creo que sería seguro agrupar eliminaciones en la categoría RR también
BateTech

2
Las inserciones y eliminaciones de @anir yes se incluyen en lecturas sucias. Ejemplo: comience una transacción, inserte 2 de 100 líneas de factura en la conexión a, ahora la conexión b lee esas 2 líneas antes de que se confirme el trx y antes de que se agreguen las otras 98 líneas, por lo que no incluye toda la información de la factura. Esta sería una lectura sucia que implica un inserto.
BateTech

28

Como se explica en este artículo , la anomalía de lectura no repetible es la siguiente:

ingrese la descripción de la imagen aquí

  1. Alice y Bob comienzan dos transacciones de la base de datos.
  2. Bob lee el registro de publicación y el valor de la columna de título es Transacciones.
  3. Alice modifica el título de un registro de publicación dado al valor de ACID.
  4. Alice confirma su transacción de base de datos.
  5. Si Bob vuelve a leer el registro de publicación, observará una versión diferente de esta fila de la tabla.

En este artículo sobre Phantom Read , puede ver que esta anomalía puede ocurrir de la siguiente manera:

ingrese la descripción de la imagen aquí

  1. Alice y Bob comienzan dos transacciones de la base de datos.
  2. Bob lee todos los registros post_comment asociados con la fila de publicación con el valor de identificador de 1.
  3. Alice agrega un nuevo registro post_comment que está asociado con la fila de la publicación que tiene el valor identificador de 1.
  4. Alice confirma su transacción de base de datos.
  5. Si Bob vuelve a leer los registros post_comment que tienen el valor de columna post_id igual a 1, observará una versión diferente de este conjunto de resultados.

Entonces, mientras que la Lectura no repetible se aplica a una sola fila, la Lectura fantasma trata sobre un rango de registros que satisfacen un criterio de filtrado de consultas dado.


3
visualización excelente @Vlad
dextermini

23

Leer fenómenos

  • Lecturas sucias : leer datos NO COMPROMETIDOS de otra transacción
  • Lecturas no repetibles : lea datos COMPROMETIDOS de unaUPDATEconsulta de otra transacción
  • Lecturas fantasma : lea datos COMPROMETIDOS de unaconsultaINSERToDELETEde otra transacción

Nota : Las declaraciones DELETE de otra transacción también tienen una probabilidad muy baja de causar lecturas no repetibles en ciertos casos. Ocurre cuando la declaración DELETE, desafortunadamente, elimina la misma fila que estaba consultando su transacción actual. Pero este es un caso raro, y es mucho más improbable que ocurra en una base de datos que tiene millones de filas en cada tabla. Las tablas que contienen datos de transacciones generalmente tienen un alto volumen de datos en cualquier entorno de producción.

También podemos observar que las ACTUALIZACIONES pueden ser un trabajo más frecuente en la mayoría de los casos de uso en lugar de INSERT o DELETES reales (en tales casos, el peligro de lecturas no repetibles solo permanece; las lecturas fantasmas no son posibles en esos casos). Esta es la razón por la cual las ACTUALIZACIONES se tratan de manera diferente a INSERT-DELETE y la anomalía resultante también se denomina de manera diferente.

También hay un costo de procesamiento adicional asociado con el manejo de INSERT-DELETEs, en lugar de solo manejar las ACTUALIZACIONES.


Beneficios de diferentes niveles de aislamiento.

  • READ_UNCOMMITTED no evita nada. Es el nivel de aislamiento cero
  • READ_COMMITTED evita solo uno, es decir, lecturas sucias
  • REPEATABLE_READ previene dos anomalías: lecturas sucias y lecturas no repetibles
  • SERIALIZABLE evita las tres anomalías: lecturas sucias, lecturas no repetibles y lecturas fantasma

Entonces, ¿por qué no simplemente configurar la transacción SERIALIZABLE en todo momento? Bueno, la respuesta a la pregunta anterior es: la configuración SERIALIZABLE hace que las transacciones sean muy lentas , lo que nuevamente no queremos.

De hecho, el consumo de tiempo de transacción está en la siguiente tasa:

SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED > READ_UNCOMMITTED

Entonces, la configuración READ_UNCOMMITTED es la más rápida .


Resumen

En realidad, necesitamos analizar el caso de uso y decidir un nivel de aislamiento para optimizar el tiempo de transacción y también prevenir la mayoría de las anomalías.

Tenga en cuenta que las bases de datos por defecto tienen la configuración REPEATABLE_READ.


1
¿ACTUALIZAR o ELIMINAR ambos pueden realizarse para lecturas no repetibles o solo es ACTUALIZAR?
Dipon Roy el

1
ACTUALIZAR o ELIMINAR ambos pueden tener lugar para lecturas no repetibles
niket patel

En realidad, podemos resumir que, en promedio, una declaración DELETE aleatoria ejecutada por otra transacción en la misma base de datos tiene una probabilidad muy baja de causar lecturas no repetibles para la transacción actual. Pero la misma declaración de eliminación tiene un 100% de posibilidades de causar una lectura fantasma para la transacción actual. Mirándolo de esa manera, mi escritura es un poco incorrecta si lo tomas palabra por palabra. Pero bueno, lo escribí intencionalmente de esta manera para aclarar las cosas al lector.
Subhadeep Ray

+1 para una explicación simple y fácil de entender. Sin embargo, creo que la mayoría de las bases de datos (oracle, mysql) tienen un nivel de aislamiento predeterminado de lectura comprometida y probablemente postgress use el valor predeterminado de repeatable_read
akila el

7

Hay una diferencia en la implementación entre estos dos tipos de niveles de aislamiento.
Para "lectura no repetible", se necesita el bloqueo de fila.
Para "lectura fantasma", se necesita un bloqueo de alcance, incluso un bloqueo de tabla.
Podemos implementar estos dos niveles utilizando el protocolo de bloqueo de dos fases .


Para implementar lectura repetible o serializable, no es necesario usar el bloqueo de fila.
a_horse_with_no_name

5

En un sistema con lecturas no repetibles, el resultado de la segunda consulta de la Transacción A reflejará la actualización en la Transacción B: verá la nueva cantidad.

En un sistema que permite lecturas fantasma, si la Transacción B inserta una nueva fila con ID = 1, la Transacción A verá la nueva fila cuando se ejecute la segunda consulta; es decir, las lecturas fantasmas son un caso especial de lectura no repetible.


No creo que la explicación de una lectura fantasma sea correcta. Puede obtener lecturas fantasmas incluso si los datos sin confirmación nunca son visibles. Vea el ejemplo en Wikipedia (vinculado en los comentarios anteriores).
Thilo

1

La respuesta aceptada indica sobre todo que la llamada distinción entre los dos en realidad no es significativa en absoluto.

Si "se recupera una fila dos veces y los valores dentro de la fila difieren entre las lecturas", entonces no son la misma fila (no la misma tupla en el lenguaje RDB correcto) y, por definición, también es el caso que "la colección de las filas devueltas por la segunda consulta son diferentes de la primera ".

En cuanto a la pregunta "qué nivel de aislamiento se debe usar", cuanto más importantes sean sus datos para alguien, en algún lugar, más será el caso de que Serializable es su única opción razonable.


0

Creo que hay alguna diferencia entre la lectura no repetible y la lectura fantasma.

No repetible significa que hay una transacción de remolque A y B. si B puede notar la modificación de A, por lo que tal vez suceda una lectura sucia, por lo que permitimos que B note la modificación de A después de que A se compromete.

Hay un nuevo problema: dejamos que B note la modificación de A después de que A se compromete, significa que A modifica un valor de fila que B tiene, a veces B leerá la fila nuevamente, por lo que B obtendrá un nuevo valor diferente con la primera vez que get, lo llamamos No repetible, para tratar el problema, dejamos que B recuerde algo (porque todavía no sé lo que se recordará) cuando B comienza.

Pensemos en la nueva solución, también podemos notar que hay un nuevo problema, porque dejamos que B recuerde algo, así que, pase lo que pase en A, B no puede verse afectada, pero si B quiere insertar algunos datos en la tabla y B verifique la tabla para asegurarse de que no haya ningún registro, pero A ha insertado estos datos, por lo que puede ocurrir algún error. Lo llamamos Phantom-read.


0

la lectura no repetible es un nivel de aislamiento y la lectura fantasma (lectura del valor comprometido por otras transacciones) es un concepto (tipo de lectura, por ejemplo, lectura sucia o lectura de instantánea). El nivel de aislamiento de lectura no repetible permite lectura fantasma pero no lecturas sucias o lecturas de instantáneas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.