¿Es la práctica incorrecta de NOLOCK (sugerencia de servidor SQL)?

125

Estoy en el negocio de crear sitios web y aplicaciones que no son de misión crítica -> eg. software de banca, vuelos espaciales, aplicación de monitoreo de cuidados intensivos, etc. Usted entiende la idea.

Entonces, con ese descargo de responsabilidad masivo, ¿es malo usar la sugerencia NOLOCK en alguna declaración SQL? Hace varios años, un compañero Administrador de SQL sugirió que debería usar NOLOCK si estoy contento con una "lectura sucia" que me dará un poco más de rendimiento de mi sistema porque cada lectura no bloquea el tabla / fila / lo que sea.

También me dijeron que es una gran solución si estoy experimentando bloqueos muertos. Entonces, comencé a seguir ese pensamiento durante unos años hasta que un gurú de SQL me ayudó con un código aleatorio y noté todas las NOLOCKS en mi código sql. Me regañaron cortésmente y él trató de explicármelo (por qué no es algo bueno) y me perdí. Sentí que la esencia de su explicación era 'es una solución de tirita a un problema más grave ... especialmente si estás experimentando un punto muerto. Como tal, arregle la raíz del problema '.

Recientemente busqué en Google al respecto y encontré esta publicación .

Entonces, ¿puede algún sql db guru sensei iluminarme?

Pure.Krome
fuente
No lo entiendo, Sam, estás diciendo que utilices el aislamiento de instantáneas si es un sitio web de lectura pesada. Pero entonces dices que SO hizo eso, ¿y es malo? o simplemente su uso de NOLOCK?
Pure.Krome

Respuestas:

67

Con la sugerencia NOLOCK, el nivel de aislamiento de la transacción para la SELECTdeclaración es READ UNCOMMITTED. Esto significa que la consulta puede ver datos sucios e inconsistentes.

Esta no es una buena idea para aplicar como regla. Incluso si este comportamiento de lectura sucia está bien para su aplicación basada en web de misión crítica, un escaneo NOLOCK puede causar un error 601 que terminará la consulta debido al movimiento de datos como resultado de la falta de protección de bloqueo.

Sugiero leer Cuando el aislamiento de instantáneas ayuda y Cuándo duele : el MSDN recomienda usar READ COMMITTED SNAPSHOT en lugar de SNAPSHOT en la mayoría de las circunstancias.

Ponis OMG
fuente
1
Rex, siéntase libre de agregar una nota sobre el aislamiento de instantáneas.
Sam Saffron
2
Sí, Sam está diciendo aislamiento de instantáneas y estás sugiriendo una instantánea confirmada de lectura. Me estoy confundiendo mucho: P (¡y todavía no he profundizado en los artículos!)
Pure.Krome
2
Es ocasionalmente útil, pero normalmente no para la producción. Lo uso con frecuencia para extraer una muestra de datos para probar o para generar informes en los que principalmente me importa el orden aproximado de magnitud donde una lectura sucia no importará.
TimothyAWiseman
NOLOCK == no me importa si se omiten las filas confirmadas, se incluyen filas no confirmadas, en casos excepcionales se devuelve la misma fila más de una vez, y en casos muy raros se devuelven filas que no coinciden con mi consulta. (ver blogs.msdn.com/b/sqlcat/archive/2007/02/01/… , encontrado en otra SO q'n sobre este tema)
Andrew Hill
106

Antes de trabajar en Stack Overflow, estaba en contra NOLOCK en el principio de que usted podría realizar una SELECTcon NOLOCKy volver resultados con los datos que pueden estar fuera de fecha o inconsistente. Un factor a tener en cuenta es cuántos registros se pueden insertar / actualizar al mismo tiempo que otro proceso puede seleccionar datos de la misma tabla. Si esto sucede mucho, entonces hay una alta probabilidad de puntos muertos a menos que use un modo de base de datos como READ COMMITED SNAPSHOT.

Desde entonces, he cambiado mi perspectiva sobre el uso NOLOCKdespués de presenciar cómo puede mejorar el SELECTrendimiento y eliminar los puntos muertos en un SQL Server cargado de forma masiva. Hay ocasiones en las que puede que no le importe que sus datos no estén exactamente comprometidos al 100% y que necesite resultados rápidamente, aunque estén desactualizados.

Hágase una pregunta cuando piense en usar NOLOCK :

¿Mi consulta incluye una tabla que tiene un alto número de INSERT/UPDATE comandos y me importa si los datos devueltos de una consulta pueden faltar estos cambios en un momento dado?

Si la respuesta es no, entonces use NOLOCK para mejorar el rendimiento.


Acabo de realizar una búsqueda rápida de la NOLOCKpalabra clave dentro de la base de código para Stack Overflow y encontré 138 instancias, por lo que la usamos en bastantes lugares.

Geoff Dalgas
fuente
77
OMI, esto es un poco simplista. Los puntos muertos se pueden eliminar mediante el uso de índices de cobertura, quitando la presión del índice agrupado.
Mitch Wheat
8
No deseo disminuir la importancia de una buena cobertura del índice. Hay veces que las consultas que usan NOLOCK pueden agregar un rendimiento adicional además de las ganancias obtenidas por los índices en las tablas con una gran cantidad de inserciones / actualizaciones. La velocidad de consulta en el desbordamiento de pila es primordial incluso a costa de datos inexactos o faltantes.
Geoff Dalgas
9
Aparentemente uno puede obtener filas duplicadas usando NOLOCK. Esto significa que tengo que rechazar tu respuesta. Lo siento.
ErikE
1
@MitchWheat A SELECT, leyendo solo desde un índice de cobertura, puede causar un punto muerto. SPID 1) comienza a SELECTdesde el índice de cobertura. SPID 2) Inicie uno UPDATEde la tabla. Actualizar luego pasa a actualizar el índice de cobertura. UPDATEalcanza un rango de índice bloqueado por SELECTy se bloquea. SPID 1) aún buscando a través del índice de cobertura, encuentra un rango bloqueado por UPDATEy se bloquea. DEADLOCK . Nada puede resolver ese punto muerto (excepto detectar el error 1205 de SQL Server y volver a intentarlo automáticamente o usarlo NOLOCK)
Ian Boyd
2
Creo que lo importante a tener en cuenta sobre esta respuesta es que era apropiado para el problema en cuestión . Dependiendo de su aplicación, el riesgo de datos obsoletos / no confirmados / duplicados / faltantes puede no valer la pena.
Desarrollador holístico
20

Si no le importan las lecturas sucias (es decir, en una situación predominantemente LEÍDA), entonces NOLOCKestá bien.

PERO , tenga en cuenta que la mayoría de los problemas de bloqueo se deben a que no tiene los índices 'correctos' para su carga de trabajo de consulta (suponiendo que el hardware esté a la altura de la tarea).

Y la explicación del gurú fue correcta. Suele ser una solución de tirita a un problema más grave.

Editar : definitivamente no estoy sugiriendo que se use NOLOCK. Creo que debería haberlo dejado claro. (Solo lo usaría alguna vez, en circunstancias extremas donde había analizado que estaba bien). Como ejemplo, hace un tiempo trabajé en algunos TSQL que habían sido rociados con NOLOCK para tratar de aliviar los problemas de bloqueo. Los eliminé todos, implementé los índices correctos y TODOS los puntos muertos desaparecieron.

Trigo Mitch
fuente
3
Hmm ... todavía no lo entiendo. Así que está bien, pero también tiene mala forma ... ¿es eso lo que estás diciendo?
Pure.Krome
Suponiendo que NUNCA te importan las lecturas sucias, entonces no te dolerá. Pero es por lo general un caso de tratar el síntoma y no la causa ...
Mitch Trigo
2
Bueno, no creo que se haya rechazado su réplica justa, creo que no abordó los errores arbitrarios que simplemente aparecen cuando usa nolock. No está bien obtener una página de error en blanco de vez en cuando en su sitio web, es una forma realmente pobre. No me gusta la afirmación de que "si no se preocupan por las lecturas sucias está bien" ... no está bien, incluso si no se preocupan por las lecturas sucias
Sam azafrán
La página en blanco que aparece cuando una consulta genera una excepción para la que no implementó la lógica de reintento. ¿Qué sucede en sus sitios cuando los resultados de ejecución de consultas con una excepción, tiene lógica de reintento en todas partes?
Sam Saffron
Tome una consulta muy bien optimizada que sepa que está alcanzando los índices adecuados. Luego agregue pistas nolock y observe cómo se acelera. Si no te importan las lecturas sucias, nunca te lastimarás con nolock.
Hardwareguy
13

Duda de que fuera un "gurú" que hubiera tenido alguna experiencia en alto tráfico ...

Los sitios web suelen estar "sucios" cuando la persona está viendo la página completamente cargada. ¿Considera un formulario que se carga desde la base de datos y luego guarda los datos que se editan? Es idiota la forma en que la gente dice que las lecturas sucias son tan no no.

Dicho esto, si tiene una serie de capas que se acumulan en sus selecciones, podría estar generando una redundancia peligrosa. Si se trata de escenarios de dinero o estado, no solo necesita lectura / escritura de datos transaccionales, sino una solución de concurrencia adecuada (algo con lo que la mayoría de los "gurús" no se molestan).

Por otro lado, si tiene una búsqueda avanzada de productos para un sitio web (es decir, algo que probablemente no se almacenará en caché y será un poco intensivo) y alguna vez ha creado un sitio con más de unos pocos usuarios concurrentes (fenomenal cuántos "expertos" no lo han hecho), es ridículo embotellar cualquier otro proceso detrás de él.

Sepa lo que significa y úselo cuando sea apropiado. Su base de datos casi siempre será su cuello de botella principal en estos días y ser inteligente al usar NOLOCK puede ahorrarle miles de infraestructura.

EDITAR: no solo ayuda con los puntos muertos, sino también cuánto vas a hacer que todos los demás esperen hasta que hayas terminado, o viceversa.

¿Usando NOLOCK Hint en EF4?

Gats
fuente
10

Ninguna de las respuestas es incorrecta, aunque quizás sea un poco confusa.

  • Cuando se consultan valores / filas individuales, siempre es una mala práctica usar NOLOCK: probablemente nunca desee mostrar información incorrecta o incluso realizar acciones sobre datos incorrectos.
  • Al mostrar información estadística aproximada, NOLOCK puede ser muy útil. Tome SO como ejemplo: sería una tontería tomar bloqueos para leer el número exacto de vistas de una pregunta, o el número exacto de preguntas para una etiqueta. A nadie le importa si declara incorrectamente 3360 preguntas etiquetadas con "sql-server" ahora, y debido a una reversión de la transacción, 3359 preguntas un segundo después.
realMarkusSchmidt
fuente
No estoy de acuerdo con tu primer punto en absoluto. SI está consultando valores / filas individuales, y está especificando una identificación única para esa fila, y sabe que ningún otro proceso accederá a ella, entonces usar nolock es perfectamente aceptable y reduce el bloqueo en una aplicación concurrente.
tuseau
1
No, no es. La fila puede cambiar por otros motivos, por ejemplo, insertar otra fila divide la página. La indexación adecuada, la instantánea confirmada de lectura y el aislamiento de instantánea son casi siempre mejores ideas.
Mark Sowul
1
@tuseau si "sabe" que ningún otro proceso será acceder a la fila, el acto de tomar una cerradura no bloqueará cualquier cosa, por lo que cuesta (prácticamente) nada,
Andrew Hill
2

Como desarrollador profesional, diría que depende. Pero definitivamente sigo los consejos de GATS y OMG Ponies. Sepa lo que está haciendo, sepa cuándo ayuda y cuándo duele y

leer consejos y otras ideas pobres

lo que podría hacerte entender más profundamente el servidor sql. Generalmente sigo la regla de que las Sugerencias SQL son MALAS, pero desafortunadamente las uso de vez en cuando cuando estoy harto de forzar al servidor SQL a hacer cosas ... Pero estos son casos raros.

luke

Luckyluke
fuente
2

Cuando el soporte de aplicaciones quería responder consultas ad-hock desde el servidor de producción usando SSMS (que no fueron atendidas mediante informes), solicité que usaran nolock. De esa manera, el negocio 'principal' no se ve afectado.

richard101
fuente
2

Estoy de acuerdo con algunos comentarios sobre la sugerencia de NOLOCK y especialmente con aquellos que dicen "úsela cuando sea apropiado". Si la aplicación está mal escrita y está usando la concurrencia de manera inapropiada, eso puede causar la escalada del bloqueo. Las tablas altamente transaccionales también se bloquean todo el tiempo debido a su naturaleza. Tener una buena cobertura de índice no ayudará con la recuperación de los datos, pero establecer NIVEL DE AISLAMIENTO para LEER NO COMPROMETIDO sí. También creo que usar la sugerencia NOLOCK es seguro en muchos casos cuando la naturaleza de los cambios es predecible. Por ejemplo, en la fabricación cuando los trabajos con viajeros están pasando por diferentes procesos con muchas inserciones de mediciones, puede ejecutar de forma segura la consulta contra el trabajo terminado con la sugerencia NOLOCK y de esta manera evitar la colisión con otras sesiones que ponen bloqueos PROMOCIONADOS o EXCLUSIVOS en la mesa /página. Los datos a los que accede en este caso son estáticos, pero pueden residir en una tabla muy transaccional con cientos de millones de registros y miles de actualizaciones / inserciones por minuto. Salud

usuario2041151
fuente
2

Creo que prácticamente nunca es correcto usar nolock.

Si está leyendo una sola fila, entonces el índice correcto significa que no necesitará NOLOCK ya que las acciones de fila individuales se completan rápidamente.

Si está leyendo muchas filas para otra cosa que no sea la visualización temporal, y le preocupa poder repetir el resultado o defenderse por el número producido, entonces NOLOCK no es apropiado.

NOLOCK es una etiqueta sustituta para "no me importa si esta respuesta contiene filas duplicadas, filas que se eliminan o filas que nunca se insertaron para comenzar debido a la reversión"

Errores que son posibles bajo NOLOCK:

  • Las filas que coinciden no se devuelven en absoluto.
  • las filas individuales se devuelven varias veces (incluidas varias instancias de la misma clave primaria)
  • Se devuelven las filas que no coinciden.

Cualquier acción que pueda causar una división de página mientras se ejecuta la selección noLock puede hacer que ocurran estas cosas. Casi cualquier acción (incluso una eliminación) puede causar una división de página.

Por lo tanto: si "sabe" que la fila no cambiará mientras está ejecutando, no use nolock, ya que un índice permitirá una recuperación eficiente.

Si sospecha que la fila puede cambiar mientras se ejecuta la consulta, y le preocupa la precisión, no use nolock.

Si está considerando NOLOCK debido a puntos muertos, examine la estructura del plan de consulta en busca de escaneos inesperados de tablas, rastree los puntos muertos y vea por qué ocurren. NOLOCK alrededor de las escrituras puede significar que las consultas que anteriormente estaban en punto muerto potencialmente escribirían la respuesta incorrecta.

Andrew Hill
fuente
2

Las mejores soluciones, cuando sea posible, son:

  • Replica tus datos (usando la replicación de registros) a una base de datos de informes.
  • Utilice instantáneas SAN y monte una versión coherente de la base de datos
  • Use una base de datos que tenga un mejor nivel de aislamiento de transacciones fundamentales

El nivel de aislamiento de la transacción SNAPSHOT se creó porque MS estaba perdiendo ventas a Oracle. Oracle utiliza registros de deshacer / rehacer para evitar este problema. Postgres usa MVCC. En el futuro, Heckaton de MS usará MVCC, pero eso está a años de estar listo para la producción.

pwy
fuente
Hay un error tipográfico arriba. Quiero decir "mejor mecanismo fundamental de aislamiento de transacciones".
pwy
1
El nivel de aislamiento de la transacción SNAPSHOT es una invención de MS. Básicamente, coloca los datos en una tabla temporal en TEMPDB. Ese DB se comparte entre todos los DB en el cuadro. Por lo tanto, querrá usar SSD para TEMPDB cuando sea posible. Probablemente sea menos esfuerzo que las otras opciones.
pwy
1

NOLOCK a menudo se explota como una forma mágica de acelerar las lecturas de la base de datos, pero trato de evitar usarlo siempre que sea posible.

El conjunto de resultados puede contener filas que aún no se han confirmado, que a menudo se deshacen más tarde.

Un error o conjunto de resultados puede estar vacío, faltar filas o mostrar la misma fila varias veces.

Esto se debe a que otras transacciones están moviendo datos al mismo tiempo que lo está leyendo.

READ COMMITTED agrega un problema adicional en el que los datos se corrompen dentro de una sola columna donde varios usuarios cambian la misma celda simultáneamente.

WonderWorker
fuente
-2

En la vida real, donde se encuentran sistemas ya escritos y al agregar índices a las tablas, se ralentiza drásticamente la carga de datos de una tabla de datos de 14 gig, a veces se ve obligado a usar WITH NOLOCK en sus informes y el procesamiento de fin de mes para que las funciones agregadas (suma , recuento, etc.) no bloquee filas, páginas, tablas y disuade el rendimiento general Fácil de decir en un nuevo sistema, nunca use WITH NOLOCK y use índices, pero agregar índices reduce drásticamente la carga de datos, y cuando me digan, bueno, altere la base del código para eliminar los índices, luego la carga masiva y luego vuelva a crear los índices, lo que está muy bien, si está desarrollando un nuevo sistema. Pero no cuando ya tienes un sistema en funcionamiento.

usuario6699628
fuente
1
¿Qué estás diciendo
Max Alexander Hanna