¿Qué es "con (nolock)" en SQL Server?

610

¿Alguien puede explicar las implicaciones del uso with (nolock)en consultas, cuando debería / no debería usarlo?

Por ejemplo, si tiene una aplicación bancaria con altas tasas de transacción y una gran cantidad de datos en ciertas tablas, ¿en qué tipos de consultas nolock estaría bien? ¿Hay casos en los que siempre debe usarlo / nunca usarlo?

Andy White
fuente
Solicité en stackoverflow.com/questions/3836282/… y stackoverflow.com/questions/3836032/… principalmente la respuesta de Jonathan Allen stackoverflow.com/questions/686724/…
Gennady Vanin Геннадий Ванин
1
un enlace aquí - mssqltips.com/sqlservertip/2470/…
Steam
1
Aquí hay un excelente resumen de las implicaciones del uso de NOLOCK blogs.msdn.com/b/davidlean/archive/2009/04/06/…
Bryan

Respuestas:

461

WITH (NOLOCK) es el equivalente a usar READ UNCOMMITED como nivel de aislamiento de transacción. Por lo tanto, corre el riesgo de leer una fila no confirmada que se revierte posteriormente, es decir, datos que nunca llegaron a la base de datos. Por lo tanto, aunque puede evitar que otras operaciones bloqueen las lecturas, conlleva un riesgo. En una aplicación bancaria con altas tasas de transacción, probablemente no será la solución correcta para cualquier problema que intente resolver con mi en mi humilde opinión.

David M
fuente
156
La mayoría de las aplicaciones bancarias pueden usar nolock de manera segura porque son transaccionales en el sentido comercial. Solo escribe nuevas filas, nunca las actualiza.
Jonathan Allen
49
@ Grauenwolf: una fila insertada pero no confirmada aún podría conducir a lecturas sucias.
saasman
16
@ Saasman: si nunca revierte las transacciones, eso no importa. Y con una tabla de solo inserción, las posibilidades de una reversión son escasas o nulas. Y si ocurren, igual lo arreglará todo en el informe de variación al final del día.
Jonathan Allen
1
Estoy atrincherado Supongo que las sugerencias de bloqueo no agregado están activadas. Para Examp:
Ross Bush
11
Si lo usa NOLOCKcon un SELECT, corre el riesgo de devolver las mismas filas más de una vez (datos duplicados) si alguna vez se insertan (o actualizan) datos en la tabla al hacer una selección.
Ian Boyd
170

La pregunta es qué es peor:

  • un punto muerto, o
  • un valor incorrecto?

Para las bases de datos financieras, los puntos muertos son mucho peores que los valores incorrectos. Sé que suena al revés, pero escúchame. El ejemplo tradicional de las transacciones de DB es que actualiza dos filas, restando de una y sumando a otra. Eso está mal.

En una base de datos financiera, utiliza transacciones comerciales. Eso significa agregar una fila a cada cuenta. Es de suma importancia que estas transacciones se completen y que las filas se escriban con éxito.

Obtener el saldo de la cuenta temporalmente incorrecto no es un gran problema, para eso sirve la reconciliación al final del día. Y es mucho más probable que ocurra un sobregiro de una cuenta porque se usan dos cajeros automáticos a la vez que debido a una lectura no confirmada de una base de datos.

Dicho esto, SQL Server 2005 corrigió la mayoría de los errores que hacía NOLOCKnecesarios. Entonces, a menos que esté utilizando SQL Server 2000 o anterior, no debería necesitarlo.

Lecturas adicionales
de versiones de nivel de fila

Jonathan Allen
fuente
22
¿Obtener un saldo de cuenta temporalmente incorrecto no es un gran problema? ¿Qué sucede si esa transacción es la que está sacando efectivo de un cajero automático sin límite de sobregiro?
Aprendizaje
13
@Aprendizaje: ¿Qué sucede si retira el dinero 30 segundos antes de que alguien cobre su tarjeta? Hasta que toda la comunicación sea totalmente instantánea, los sobregiros serán un hecho real.
Jonathan Allen
66
+1 En la aplicación financiera (en todas partes, no solo en bancos), no hay actualizaciones ni eliminaciones. Incluso las operaciones incorrectas se corrigen insertando registros. ¿Cuál es este término en inglés? ¿Es "storno"? Google no me ayudó a responder esta pregunta
Gennady Vanin Геннадий Ванин
77
Entrada tardía ... los puntos muertos deben ser atrapados y reintentados Las lecturas sucias tienen consecuencias
gbn
44
@ JonathanAllen solo para tu información, el término es UTmost, no UP.
Jimmy D
57

Lamentablemente, no se trata solo de leer datos no confirmados. En segundo plano, puede terminar leyendo páginas dos veces (en el caso de una división de página), o puede perder las páginas por completo. Por lo tanto, sus resultados pueden ser muy sesgados.

Mira el artículo de Itzik Ben-Gan . Aquí hay un extracto:

"Con la sugerencia NOLOCK (o configurando el nivel de aislamiento de la sesión como LEÍDO NO COMPROMETIDO), le dice a SQL Server que no espera consistencia, por lo que no hay garantías. Tenga en cuenta que" datos inconsistentes "no solo significan que es posible que vea cambios no confirmados que luego fueron revertidos, o cambios de datos en un estado intermedio de la transacción. También significa que en una consulta simple que escanea todos los datos de tabla / índice, SQL Server puede perder la posición de escaneo, o puede terminar obteniendo la misma fila dos veces ".

sqlbelle
fuente
55
Un poco más abajo, explica cómo obtener la misma fila dos veces: recrearé la tabla T1 de modo que el índice agrupado en col1 se definirá como un índice único con la opción IGNORE_DUP_KEY. Esto significa que no pueden existir valores duplicados en col1, y también que un intento de insertar una clave duplicada no fallará la transacción y generará un error, sino que solo generará una advertencia. Si no usa esta opción extraña, probablemente no tenga que preocuparse por obtener filas dos veces
JanHudecek
Todavía puede obtener filas duplicadas incluso sin la opción cableada, si su consulta aprovecha un índice que no es único, por ejemplo. Sin embargo, esto no es exclusivo de nolock.
RMD
54

El ejemplo de libro de texto para el uso legítimo de la sugerencia nolock es el muestreo de informes en una base de datos OLTP de alta actualización.

Para tomar un ejemplo tópico. Si un gran banco de la calle de los EE. UU. Quisiera realizar un informe por hora buscando los primeros signos de una ejecución a nivel de ciudad en el banco, una consulta nolock podría escanear tablas de transacciones que sumen depósitos de efectivo y retiros de efectivo por ciudad. Para dicho informe, el pequeño porcentaje de error causado por las transacciones de actualización revertidas no reduciría el valor del informe.

saasman
fuente
31

No estoy seguro de por qué no está envolviendo transacciones financieras en transacciones de bases de datos (como cuando transfiere fondos de una cuenta a otra, no compromete un lado de la transacción a la vez, es por eso que existen transacciones explícitas). Incluso si su código es un cerebro inteligente para las transacciones comerciales como parece, todas las bases de datos transaccionales tienen el potencial de hacer retrocesos implícitos en caso de errores o fallas. Creo que esta discusión está muy por encima de tu cabeza.

Si tiene problemas de bloqueo, implemente el control de versiones y limpie su código.

Sin bloqueo no solo devuelve valores incorrectos, devuelve registros fantasma y duplicados.

Es un error común pensar que siempre hace que las consultas se ejecuten más rápido. Si no hay bloqueos de escritura en una tabla, no hay diferencia. Si hay bloqueos en la tabla, puede hacer que la consulta sea más rápida, pero hay una razón por la cual se inventaron bloqueos en primer lugar.

Para ser justos, aquí hay dos escenarios especiales donde una sugerencia de nolock puede proporcionar utilidad

1) La base de datos del servidor SQL anterior a 2005 que necesita ejecutar una consulta larga contra la base de datos OLTP en vivo, esta puede ser la única forma

2) La aplicación mal escrita que bloquea registros y devuelve el control a la interfaz de usuario y los lectores se bloquean indefinidamente. Nolock puede ser útil aquí si la aplicación no se puede arreglar (terceros, etc.) y la base de datos es anterior a 2005 o no se puede activar el control de versiones.

Andrés
fuente
11
Estoy de acuerdo con usted en que NOLOCK no debe usarse para compensar un código mal escrito. Sin embargo, creo que su ataque a Johnathan no está justificado ya que nunca mencionó las transacciones de la base de datos . Simplemente estaba señalando que las aplicaciones financieras generalmente no permiten modificaciones en los registros (obviamente, hay algunas excepciones). En su ejemplo de transferencia de fondos, dice que sería extraño que mutara el valor del saldo de la cuenta en lugar de agregar una entrada de débito / crédito a una especie de libro mayor.
chrnola
19
Cuando los fondos se transfieren de una cuenta a otra en diferentes bancos, ¿qué crees que sucede? ¿Alguna base de datos uber se bloquea en una mesa en Bank of America y otra en Wells Fargo? No. Una transacción financiera se escribe en cada uno y luego un proceso de fin de día verifica que todos los registros coincidan.
Jonathan Allen
24

NOLOCK es equivalente a READ UNCOMMITTED , sin embargo, Microsoft dice que no debe usarlo UPDATEo DELETEdeclaraciones:

Para declaraciones UPDATE o DELETE: esta característica se eliminará en una versión futura de Microsoft SQL Server. Evite usar esta función en nuevos trabajos de desarrollo y planee modificar las aplicaciones que actualmente usan esta función.

http://msdn.microsoft.com/en-us/library/ms187373.aspx

Este artículo se aplica a SQL Server 2005, por lo que la compatibilidad NOLOCKexiste si está utilizando esa versión. Para preparar su código en el futuro (suponiendo que haya decidido usar lecturas sucias), puede usar esto en sus procedimientos almacenados:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Seibar
fuente
21

Puede usarlo cuando solo está leyendo datos, y realmente no le importa si podría o no recuperar datos que aún no se han confirmado.

Puede ser más rápido en una operación de lectura, pero realmente no puedo decir cuánto.

En general, recomiendo no usarlo: leer datos no confirmados puede ser un poco confuso en el mejor de los casos.

marc_s
fuente
1
Sería bueno que mencionaras el hecho de que SQL Server 2005 tiene versiones de fila para que los nolocks ya no sean necesarios.
Jonathan Allen
Bueno, el "con (nolock)" todavía tiene su lugar incluso en SQL Server 2005, pero los beneficios son cada vez más delgados, eso es cierto.
marc_s
18

Otro caso en el que generalmente está bien es en una base de datos de informes, donde los datos tal vez ya están obsoletos y las escrituras simplemente no suceden. Sin embargo, en este caso, el administrador debe establecer la opción en el nivel de la base de datos o la tabla cambiando el nivel de aislamiento predeterminado.

En el caso general: puede usarlo cuando esté muy seguro de que está bien leer datos antiguos. Lo importante para recordar es que es muy fácil equivocarse . Por ejemplo, incluso si está bien al momento de escribir la consulta, ¿está seguro de que algo no cambiará en la base de datos en el futuro para hacer que estas actualizaciones sean más importantes?

También voy a la segunda idea de que probablemente no sea una buena idea en la aplicación bancaria. O aplicación de inventario. O en cualquier lugar donde esté pensando en transacciones.

Joel Coehoorn
fuente
44
Como persona que trabaja en aplicaciones bancarias, tengo que decir que los bloqueos no son un problema. Los registros transaccionales, es decir, las filas que se insertan pero nunca se actualizan o eliminan, son sorprendentemente resistentes a los problemas de lectura de datos no confirmados.
Jonathan Allen
15

Respuesta simple: cuando su SQL no está alterando los datos, y tiene una consulta que podría interferir con otra actividad (mediante bloqueo).

Vale la pena considerar cualquier consulta utilizada para los informes, especialmente si la consulta lleva más de, por ejemplo, 1 segundo.

Es especialmente útil si tiene informes de tipo OLAP que está ejecutando en una base de datos OLTP.

Sin embargo, la primera pregunta es "¿por qué me preocupo por esto?" En mi experiencia, eludir el comportamiento de bloqueo predeterminado a menudo ocurre cuando alguien está en modo "probar cualquier cosa" y este es un caso donde las consecuencias inesperadas no son improbables. Con demasiada frecuencia es un caso de optimización prematura y puede quedar fácilmente incrustado en una aplicación "por si acaso". Es importante entender por qué lo está haciendo, qué problema resuelve y si realmente tiene el problema.

dkretz
fuente
11

Respuesta corta:

Solo se usa WITH (NOLOCK)en la instrucción SELECT en tablas que tienen un índice agrupado.

Respuesta larga:

WITH (NOLOCK) a menudo se explota como una forma mágica de acelerar las lecturas de la base de datos.

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

Si WITH (NOLOCK) se aplica a una tabla que tiene un índice no agrupado, las transacciones pueden cambiar los índices de fila a medida que los datos de la fila se transmiten a la tabla de resultados. Esto significa que al conjunto de resultados pueden faltar filas o mostrar la misma fila varias veces.

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
La lectura de datos no confirmados es aceptable si no cambia la decisión final. Por ejemplo, si está tratando de proyectar cuánto dinero va a ganar su tienda minorista en los próximos 6 meses, ver que Tammy compró 2 rollos de toallas de papel cuando realmente compró 3 no va a cambiar su opinión sobre el futuro .
Jonathan Allen el
1
Si su filtro incluye ahora, sus datos serán inexactos en el momento en que ejecute la consulta. Si su filtro solo incluye datos históricos, el uso READ UNCOMITTED no lo afectará en absoluto. Hay una razón por la que se incluyó en el estándar ANSI.
Jonathan Allen el
2
Nunca digas nunca. Si NECESITA que los datos sean 100% precisos, entonces no debe usar nolock. Para mí, este generalmente no es el caso. Cuando se presentan datos a un usuario, para el momento en que actúan sobre los datos, es posible que ya hayan cambiado de todos modos, pero lo más probable es que no lo hayan hecho, y la contención del bloqueo no justifica los retrasos en la respuesta.
Perpetidor
Sigamos con sistemas dignos de existencia. No olvides que Tammy tiene un cerebro perfectamente decente, por lo que usar una base de datos para registrar pequeñas compras de toallas de papel de las que nadie se da cuenta es absurdo en el mejor de los casos. Nuestro enfoque son los sistemas que son realmente importantes, por ejemplo, hacer que las personas paguen a tiempo, responder a emergencias, etc. Es de gran beneficio que el uso de WITH (NOLOCK) sea entendido por las personas que programan cualquier sistema digno de existir. Cuando una persona puede hacer un mejor trabajo que una base de datos, considere reutilizar esos recursos.
WonderWorker
10

Mis 2 centavos, tiene sentido usar WITH (NOLOCK) cuando necesita generar informes. En este punto, los datos no cambiarían mucho y no querría bloquear esos registros.

SoftwareGeek
fuente
2
Creo que WITH (NoLOCK) es mejor si no te importan los cambios actuales.
Abdul Saboor
9

Si está manejando transacciones financieras, nunca querrá usarlas nolock. nolockse utiliza mejor para seleccionar de tablas grandes que tienen muchas actualizaciones y no le importa si el registro que obtiene podría estar desactualizado.

Los registros financieros (y casi todos los demás registros en la mayoría de las aplicaciones) nolockcausarían estragos, ya que potencialmente podría leer los datos de un registro que se estaba escribiendo y no obtener los datos correctos.

Andrew Hare
fuente
55
Sorprendentemente, cuando se trabaja con datos financieros, esto no es un problema. Como las filas nunca se editan y las cuentas se concilian al final del día, leer datos falsos temporalmente no hace nada.
Jonathan Allen
8

Solía ​​recuperar un "próximo lote" para hacer cosas. No importa en este caso qué elemento exacto, y tengo muchos usuarios ejecutando esta misma consulta.

Otávio Décio
fuente
1
Hacemos algo similar para presentar una tarea en segundo plano con una cola de trabajo por hacer. Si, cuando llega a un registro en particular, ya no existe / coincide con los criterios de selección, simplemente pasa al siguiente.
TripeHound
7

Use nolock cuando esté de acuerdo con los datos "sucios". Lo que significa que nolock también puede leer datos que están en proceso de modificación y / o datos no confirmados.

En general, no es una buena idea usarlo en un entorno de alta transacción y es por eso que no es una opción predeterminada en la consulta.

Aprendizaje
fuente
3
El único momento que lo necesita es en un entorno de alta transacción. Si sus tablas están en su mayoría inactivas, entonces no ganaría nada con ellas.
Jonathan Allen
7

Utilizo con (nolock) sugerencia particularmente en bases de datos SQLServer 2000 con alta actividad. Sin embargo, no estoy seguro de que sea necesario en SQL Server 2005. Recientemente agregué esa sugerencia en un SQL Server 2000 a pedido del DBA del cliente, porque notó muchos bloqueos de registros SPID.

Todo lo que puedo decir es que usar la pista NO nos ha hecho daño y parece haber hecho que el problema de bloqueo se resuelva por sí solo. El DBA en ese cliente en particular básicamente insistió en que usáramos la pista.

Por cierto, las bases de datos con las que trato son back-end de los sistemas empresariales de reclamaciones médicas, por lo que estamos hablando de millones de registros y más de 20 tablas en muchas combinaciones. Normalmente agrego una sugerencia WITH (nolock) para cada tabla en la unión (a menos que sea una tabla derivada, en cuyo caso no puede usar esa sugerencia en particular)

usuario52212
fuente
1
SQL Server 2005 agregó "versiones de fila" que debería reducir en gran medida la necesidad de nolocks. Recientemente hemos actualizado y no estamos entrenando a nuestros DBA para que dejen de usarlos.
Jonathan Allen
5

La respuesta más simple es una pregunta simple: ¿necesita que sus resultados sean repetibles? En caso afirmativo, NOLOCKS no es apropiado bajo ninguna circunstancia

Si no necesita repetibilidad, los nolocks pueden ser útiles, especialmente si no tiene control sobre todos los procesos que se conectan a la base de datos de destino.

Ed Green
fuente