sql-server - tablock - sqlserver with no lock
sintaxis para nolock en sql (5)
He visto sentencias de SQL utilizando nolock y con (nolock), por ejemplo,
select * from table1 nolock where column1 > 10
Y
select * from table1 with(nolock) where column1 > 10
¿Cuál de las afirmaciones anteriores es correcta y por qué?
Ambos son sintácticamente correctos.
NOLOCK se convertirá en el alias de table1.
WITH (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 retrotraen posteriormente.
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ás leyendo.
LEER COMPROMETIDO agrega un problema adicional donde los datos se corrompen dentro de una sola columna donde varios usuarios cambian la misma celda simultáneamente.
También hay otros efectos secundarios, que resultan en el sacrificio del aumento de velocidad que esperabas ganar en primer lugar.
Ahora ya sabes, nunca lo uses de nuevo.
Ambos son técnicamente correctos, sin embargo, no usar la palabra clave WITH ha quedado en desuso a partir de SQL 2005, así que acostúmbrese a usar la palabra clave WITH: respuesta corta, use la palabra clave WITH.
La lista de características en desuso se encuentra en Características del motor de base de datos en desuso en SQL Server 2008 :
- Especificando NOLOCK o READUNCOMMITTED en la cláusula FROM de una instrucción UPDATE o DELETE.
- Especificar sugerencias de tabla sin utilizar la palabra clave WITH.
- Sugerencia de tabla HOLDLOCK sin paréntesis
- Uso de un espacio como separador entre las sugerencias de la tabla.
- La aplicación indirecta de sugerencias de tabla a una invocación de una función con valores de tabla de declaraciones múltiples (TVF) a través de una vista.
Todos ellos están en la lista de características que se eliminarán algunas veces después de la próxima versión de SQL, lo que significa que es probable que sean compatibles con la versión enxt solo con un nivel de compatibilidad de base de datos inferior.
Dicho esto, mi 2c sobre el tema es como tal:
- Tanto
from table nolock
comofrom table with(nolock)
están equivocados. Si necesita lecturas sucias, debe usar niveles de aislamiento de transacción apropiados:set transaction isolation level read uncommitted
. De esta manera, el nivel de aislamiento utilizado se establece y controla de manera explícita desde un solo ''botón'', en lugar de extenderse a través de la fuente y sujeto a todas las peculiaridades de las sugerencias de tabla (aplicación indirecta a través de vistas y TVF, etc.). Las lecturas sucias son una abonación. Lo que se necesita, en el 99,99% de los casos, es la reducción de la contención, no leer los datos no confirmados. La contención se reduce al escribir las consultas adecuadas contra un esquema bien diseñado y, si es necesario, implementando el aislamiento de instantáneas. La mejor solución, que resuelve los trabajos casi siempre, salvo algunos casos extremos, es habilitar la lectura de instantáneas comprometidas en la base de datos y dejar que el motor haga su magia:
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON
A continuación, elimine TODOS los consejos de los seleccionados.
La primera afirmación no bloquea nada, mientras que la segunda lo hace. Cuando probé esto ahora mismo en SQL Server 2005, en
select * from table1 nolock where column1 > 10 --INCORRECT
"nolock" se convirtió en el alias, dentro de esa consulta, de table1.
select * from table1 with(nolock) where column1 > 10
Realiza la funcionalidad nolock deseada. ¿Escéptico? En una ventana separada, ejecute
BEGIN TRANSACTION
UPDATE tabl1
set SomeColumn = ''x'' + SomeColumn
para bloquear la tabla, y luego intente cada instrucción de bloqueo en su propia ventana. El primero se bloqueará, a la espera de que se libere el bloqueo, y el segundo se ejecutará inmediatamente (y mostrará los "datos sucios"). No te olvides de emitir
ROLLBACK
cuando termines.
Utilice "CON (NOLOCK)".