¿Por qué utilizar un nivel de aislamiento LEER NO COMPROMETIDO?


225

En inglés simple, ¿cuáles son las desventajas y ventajas de usar

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

en una consulta para aplicaciones .NET y aplicaciones de servicios de informes?

Respuestas:


210

Este nivel de aislamiento permite lecturas sucias. Una transacción puede ver cambios no confirmados realizados por otra transacción.

Para mantener el nivel más alto de aislamiento, un DBMS generalmente adquiere bloqueos en los datos, lo que puede resultar en una pérdida de concurrencia y una alta sobrecarga de bloqueo. Este nivel de aislamiento relaja esta propiedad.

Es posible que desee consultar el artículo de Wikipedia sobreREAD UNCOMMITTED algunos ejemplos y lecturas adicionales.


También puede estar interesado en consultar el artículo del blog de Jeff Atwood sobre cómo él y su equipo abordaron un problema de punto muerto en los primeros días de Stack Overflow. De acuerdo con Jeff:

Pero es nolockpeligroso? ¿Podría terminar leyendo datos no válidos con read uncommittedon? Si, en teoria. No encontrará escasez de astronautas de arquitectura de bases de datos que comienzan a dejar caer la ciencia de ACID sobre usted y todo, pero activan la alarma de incendio del edificio cuando les dice que desea probarnolock . Es cierto: la teoría da miedo. Pero esto es lo que pienso: "En teoría no hay diferencia entre teoría y práctica. En la práctica sí la hay".

Nunca recomendaría usar nolock como una solución general de aceite de serpiente "bueno para lo que te aflige" para cualquier problema de bloqueo de la base de datos que puedas tener. Primero debe intentar diagnosticar la fuente del problema.

Pero en la práctica, agregar nolocka consultas que usted sabe absolutamente que son asuntos simples y directos de solo lectura nunca parece generar problemas ... Siempre y cuando sepa lo que está haciendo.

Una alternativa al READ UNCOMMITTEDnivel que puede considerar es el READ COMMITTED SNAPSHOT. Citando a Jeff nuevamente:

Las instantáneas se basan en un método de seguimiento de cambio de datos completamente nuevo ... más que un simple cambio lógico, requiere que el servidor maneje los datos físicamente de manera diferente. Una vez que este nuevo método de seguimiento de cambio de datos está habilitado, crea una copia o una instantánea de cada cambio de datos. Al leer estas instantáneas en lugar de datos en vivo en momentos de contención, ya no se necesitan bloqueos compartidos en las lecturas, y el rendimiento general de la base de datos puede aumentar.


13
El autor parece implicar que la lectura no confirmada / sin bloqueo devolverá los datos confirmados por última vez. Según tengo entendido, leer no confirmado devolverá cualquier valor que se haya configurado por última vez, incluso de transacciones no confirmadas. Si es así, el resultado no sería recuperar datos "unos pocos segundos desactualizados". (O al menos podría hacerlo si la transacción que escribió los datos que lee se revierte) estaría recuperando datos que no existen o que nunca se confirmaron. ¿Estoy equivocado?
xr280xr

44
Gran respuesta. Por cierto, Oracle tiene una "instantánea" de forma predeterminada desde que la conozco, probablemente décadas antes de que Sql Server la introdujera. Estaba bastante decepcionado cuando comencé con SQL Server y descubrí que todos los problemas de concurrencia se resolvieron utilizando mecanismos de bloqueo "primitivos". Nunca vi "Leer sin confirmar" en Oracle. Y el practicante está tan feliz como los astronautas.
Stefan Steinegger

13
READ UNCOMMITTEDTambién puede hacer que leas filas dos veces o que te pierdas filas enteras . Si se produce una división de página mientras está leyendo, puede perder fragmentos enteros de datos. WITH(NOLOCK)solo debe usarse si la precisión de los resultados no es importante
Ian Boyd

8
@DanielNolan, Recomendar ese artículo es peligroso porque Jeff no sabía lo que estaba haciendo . La lectura no confirmada solo tiene sentido porque la lectura de datos nunca se modificará. Intentar usar eso para leer tablas en las que se escribiría significa que en la práctica leerá algo que se revierte. No es solo que estés leyendo datos que tienen unos pocos segundos de antigüedad, sino que .................................. ................... ‌ ‌ ........................... ....
Pacerier

55
................................... están leyendo datos que nunca se comprometen. Esa es la definición misma de lecturas corruptas. Y si va a escribir en función de los resultados de esas lecturas no confirmadas, en la práctica escribirá datos corruptos. Además, el artículo afirmaba que "MySQL, que creció en aplicaciones web, es mucho menos pesimista fuera de la caja que SQL Server". No es cierto, Sql Server funciona a nivel de lectura confirmada de forma predeterminada, mientras que MySQL funciona a lecturas repetibles de forma predeterminada, a cinco niveles de lectura no confirmada.
Pacerier

36

Esto puede ser útil para ver el progreso de las consultas de inserción largas, hacer estimaciones aproximadas (como COUNT(*)o aproximadas SUM(*)), etc.

En otras palabras, los resultados que devuelven las consultas de lectura sucia están bien siempre que los trate como estimaciones y no tome decisiones críticas basadas en ellos.


36

Mi caso de uso favorito read uncommitedes para depurar algo que sucede dentro de una transacción.

Inicie su software bajo un depurador, mientras recorre las líneas de código, abre una transacción y modifica su base de datos. Mientras se detiene el código, puede abrir un analizador de consultas, establecerlo en el nivel de aislamiento de lectura no comprometida y realizar consultas para ver qué está sucediendo.

También puede usarlo para ver si los procedimientos de ejecución prolongada están bloqueados o actualizan correctamente su base de datos.

Es excelente si a su empresa le encanta realizar procedimientos almacenados demasiado complejos.


66
A mi empresa le encanta realizar procedimientos almacenados demasiado complejos. ¡Qué gran idea para solucionar problemas!
Brandon

22

La ventaja es que puede ser más rápido en algunas situaciones. La desventaja es que el resultado puede ser incorrecto (los datos que aún no se han confirmado podrían devolverse) y no hay garantía de que el resultado sea repetible.

Si te importa la precisión, no uses esto.

Más información está en MSDN :

Implementa la lectura sucia o el bloqueo de nivel 0 de aislamiento, lo que significa que no se emiten bloqueos compartidos y no se respetan bloqueos exclusivos. Cuando se establece esta opción, es posible leer datos no confirmados o sucios; los valores en los datos se pueden cambiar y las filas pueden aparecer o desaparecer en el conjunto de datos antes del final de la transacción. Esta opción tiene el mismo efecto que establecer NOLOCK en todas las tablas en todas las instrucciones SELECT en una transacción. Este es el menos restrictivo de los cuatro niveles de aislamiento.


¿Cómo afectaría esto a la velocidad de la consulta?
Kip Real

11
@Kip: las selectdeclaraciones no tendrían que esperar para adquirir bloqueos compartidos en los recursos que están bloqueados exclusivamente por otras transacciones.
Jarrod Dixon

15

¿Cuándo está bien usar READ UNCOMMITTED?

Regla de oro

Bueno : grandes informes agregados que muestran totales en constante cambio.

Arriesgado : Casi todo lo demás.

La buena noticia es que la mayoría de los informes de solo lectura entran en esa categoría Buena .

Mas detalle...

Ok para usarlo:

  • Casi todos los informes agregados orientados al usuario para datos actuales y no estáticos, por ejemplo, ventas hasta la fecha. Se corre el riesgo de un margen de error (tal vez <0.1%) que es mucho más bajo que otros factores de incertidumbre como el error de entrada o simplemente la aleatoriedad de cuándo se registran exactamente los datos minuto a minuto.

Eso cubre probablemente la mayoría de lo que haría un departamento de Business Intelligence en, por ejemplo, SSRS. La excepción, por supuesto, es cualquier cosa con signos $ delante. Muchas personas representan el dinero con mucho más celo que el aplicado a las métricas centrales relacionadas requeridas para atender al cliente y generar ese dinero. (Culpo a los contadores).

Cuando arriesgado

  • Cualquier informe que baje al nivel de detalle. Si se requiere ese detalle, generalmente implica que cada fila será relevante para una decisión. De hecho, si no puede extraer un pequeño subconjunto sin bloquearlo, podría ser por la buena razón de que se está editando actualmente.

  • Información histórica. Rara vez hace una diferencia práctica, pero mientras que los usuarios entienden que los datos que cambian constantemente no pueden ser perfectos, no sienten lo mismo sobre los datos estáticos. Las lecturas sucias no duelen aquí, pero las lecturas dobles pueden ocasionalmente serlo. Dado que de todos modos no debería tener bloques en los datos estáticos, ¿por qué arriesgarse?

  • Casi todo lo que alimenta una aplicación que también tiene capacidades de escritura.

Cuando incluso el escenario OK no está bien.

  • ¿Hay aplicaciones o procesos de actualización que utilicen grandes transacciones individuales? ¿Los que eliminan y luego vuelven a insertar muchos registros sobre los que informa? En ese caso, realmente no se puede usar NOLOCKen esas tablas para nada.

Buen punto sobre los informes. En realidad, la primera idea que se me ocurrió fue si debería usarlo read uncommittedpara aplicaciones web cuando el usuario ve alguna cuadrícula de interfaz de usuario donde la precisión de los datos no es tan importante. El usuario solo quiere una descripción rápida de los registros que podrían estar allí, y tal vez con algo de paginación, clasificación y filtrado. Solo cuando el usuario hace clic en el botón Editar, intento leer el registro más reciente con un nivel de aislamiento más estricto. ¿No debería ser mejor este enfoque en términos de rendimiento?
JustAMartin

Sí, creo que es razonable. Recuerde que el problema más importante es asegurarse de que los datos no hayan sido modificados por otra persona entre el momento de presionar el botón de edición y el momento del envío. Puede manejar eso iniciando una transacción obteniendo los datos como select item from things with (UPDLOCK). Ponga un tiempo de espera rápido allí para que si no puede adquirir el bloqueo rápidamente, le diga al usuario que está siendo editado. Eso lo mantendrá a salvo no solo de los usuarios sino también de los desarrolladores. El único problema aquí es que debes comenzar a pensar en los tiempos de espera y en cómo manejarlos en la interfaz de usuario.
Adamantish

6

Con respecto a los informes, lo usamos en todas nuestras consultas de informes para evitar que una consulta empañe las bases de datos. Podemos hacerlo porque estamos obteniendo datos históricos, no datos de hasta el microsegundo.


4

Use READ_UNCOMMITTED en una situación en la que es poco probable que cambie la fuente.

  • Al leer datos históricos. por ejemplo, algunos registros de implementación que ocurrieron hace dos días.
  • Al leer metadatos nuevamente. por ejemplo, aplicación basada en metadatos.

No use READ_UNCOMMITTED cuando sepa que la fuente puede cambiar durante la operación de recuperación.


1
Siento que se aplica lo contrario. En primer lugar, los datos estáticos deben leerse bien sin bloques. Si no bloquean entonces ahora ha descubierto que hay un importante problema de la transacción que cuelga de arreglar. Además, los usuarios esperarán que esto coincida con el último decimal que imprimieron para el informe anual del año pasado. En general, no esperan lo mismo de los informes que saben que están en constante cambio. Esto no se aplica a informes financieros detallados o extremadamente urgentes, pero si 1 error de entrada en 1000 es tolerable, también lo es READ UNCOMMITTED.
Adamantish

TLDR: si los datos no cambian, no necesita LEER SIN COMPROMISAR porque de todos modos no hay bloques. Si te equivocas y cambia, es bueno que hayas bloqueado a los usuarios para que no obtengan datos más sucios de lo esperado.
Adamantish

Sí, tiendo a estar de acuerdo con @Adamantish aquí: puede beneficiarse de la READ UNCOMMITTEDmayoría de las situaciones en las que sus datos se utilizan activamente y desea reducir la carga en el servidor para evitar posibles puntos muertos y reversiones de transacciones solo porque algunos usuarios abusaron descuidadamente " Actualizar "en una página web con una cuadrícula de datos. Los usuarios que ven un montón de registros al mismo tiempo, generalmente no les importa mucho si los datos están un poco desactualizados o parcialmente actualizados. Solo cuando un usuario está a punto de editar un registro, es posible que desee proporcionarle los datos más precisos.
JustAMartin

2

Esto le dará lecturas sucias y le mostrará transacciones que aún no se han confirmado. Esa es la respuesta más obvia. No creo que sea una buena idea usar esto solo para acelerar sus lecturas. Hay otras formas de hacerlo si utiliza un buen diseño de base de datos.

También es interesante notar lo que no está sucediendo. READ UNCOMMITTED no solo ignora otros bloqueos de tabla. Tampoco está causando ningún bloqueo en sí mismo.

Considere que está generando un informe grande o está migrando datos de su base de datos utilizando una instrucción SELECT grande y posiblemente compleja. Esto provocará un bloqueo compartido que se puede escalar a un bloqueo de tabla compartido durante la duración de su transacción. Se pueden leer otras transacciones de la tabla, pero las actualizaciones son imposibles. Esta puede ser una mala idea si se trata de una base de datos de producción, ya que la producción puede detenerse por completo.

Si está utilizando LEER NO COMPROMETIDO, no establecerá un bloqueo compartido en la tabla. Puede obtener el resultado de algunas transacciones nuevas o puede no depender de dónde se insertaron los datos de la tabla y cuánto tiempo ha leído su transacción SELECT. También puede obtener los mismos datos dos veces si, por ejemplo, se produce una división de página (los datos se copiarán a otra ubicación en el archivo de datos).

Por lo tanto, si es muy importante para usted que los datos se puedan insertar mientras realiza su SELECCIÓN, LEER NO COMPROMETIDO puede tener sentido. Debe tener en cuenta que su informe puede contener algunos errores, pero si se basa en millones de filas y solo unas pocas se actualizan al seleccionar el resultado, esto puede ser "lo suficientemente bueno". Su transacción también puede fallar en conjunto, ya que la unicidad de una fila puede no estar garantizada.

Una mejor manera puede ser usar el NIVEL DE AISLAMIENTO INSTANTÁNEO, pero sus aplicaciones pueden necesitar algunos ajustes para usarlo. Un ejemplo de esto es si su aplicación toma un bloqueo exclusivo en una fila para evitar que otros lo lean y entren en modo de edición en la interfaz de usuario. El NIVEL DE AISLAMIENTO SNAPSHOT también viene con una considerable penalización de rendimiento (especialmente en el disco). Pero puede superar eso arrojando hardware sobre el problema. :)

También puede considerar restaurar una copia de seguridad de la base de datos para usarla para informar o cargar datos en un almacén de datos.


0

Se puede usar para una tabla simple, por ejemplo, en una tabla de auditoría de solo inserción, donde no hay actualización en la fila existente y no hay fk en otra tabla. El inserto es un inserto simple, que tiene poca o ninguna posibilidad de reversión.


-7

Siempre uso READ UNCOMMITTED ahora. Es rápido con los menores problemas. Cuando use otros aislamientos, casi siempre encontrará algunos problemas de bloqueo.

Siempre que use los campos de Incremento automático y preste un poco más de atención a las inserciones, entonces está bien, y puede despedirse de los problemas de bloqueo.

Puede cometer errores con READ UNCOMMITED pero, para ser honesto, es muy fácil asegurarse de que sus insertos sean una prueba completa. Las inserciones / actualizaciones que utilizan los resultados de una selección son lo único que debe tener en cuenta. (Use READ COMMITTED aquí, o asegúrese de que las lecturas sucias no causen problemas)

Así que vaya a las lecturas sucias (especialmente para grandes informes), su software se ejecutará sin problemas ...


66
Esto es muy inexacto y solo toca la superficie de los problemas que pueden ocurrir con nolock. Las páginas pueden dividirse, las uniones pueden fallar, puede leer datos inexistentes o datos duplicados. No hay forma de hacer que su uso sea infalible: no puede confiar en la precisión de nada por debajo de este nivel de aislamiento. LEA EL COMPROMISO COMPROMETIDO es una "panacea falsa" menos peligrosa
Mark Sowul

@ MarkSowul El voto negativo de esta respuesta me parece injusto. @Clive tenía claro que cambiaría Committedpor inserciones y actualizaciones. En cuanto a otros problemas, también demostró conocimiento de los problemas de división de página al mencionar el uso de una clave de incremento automático. Estoy de acuerdo con él en que casi todos los informes en vivo hechos para ser leídos por un humano pueden tolerar ligeras discrepancias en el último decimal. Estoy de acuerdo en que es una historia diferente para listados detallados o datos destinados a ser leídos y transformados a máquina, y Clive también.
Adamantish

1
Este comentario también demuestra una falta de comprensión total de los posibles problemas que vienen con nolock. "Pequeñas discrepancias en el último decimal" apenas lo cubre. Incluso tocar el "solo usar lectura comprometida para inserciones / actualizaciones" es incorrecto como consejo general (¿qué pasa si es "insertar un registro si no existe"?). En cualquier caso, "[leer sin confirmar] es rápido con el menor número de problemas" es categóricamente incorrecto.
Mark Sowul

Para el registro, estoy de acuerdo con su respuesta, Adamantish: agregaciones más o menos precisas y poco más.
Mark Sowul
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.