¿Por NOLOCK se ignora “en la cláusula FROM que se aplican a la tabla de destino de una instrucción UPDATE o DELETE”?

StackOverflow https://stackoverflow.com/questions/4322368

Pregunta

Estoy confundido por la frase BOL:

  

"READUNCOMMITTED y NOLOCK no se pueden especificar para las tablas modificadas por inserción, actualización o las operaciones de borrado. Optimizador de consultas de SQL Server ignora los consejos READUNCOMMITTED y NOLOCK en la cláusula FROM que se aplican a la tabla de destino de una instrucción UPDATE o DELETE" [1]

Por ejemplo, si escribo

--script 1) 
UPDATE Test SET Txt=(Select Txt from TEST WITH(NOLOCK) where ID=1) 
WHERE ID=1

se ejecuta sin errores (o advertencias) y es probablemente equivalente a

--script 2)
set transaction isolation level SERIALIZABLE;
begin tran
Declare @nvarm nvarchar(max);

Select @nvarm=Txt from Test where ID=1;
--Select @nvarm;
UPDATE Test  SET Txt=@nvarm  WHERE ID=1;
commit;

que también se ejecuta sin errores o advertencias.
Es equivalente?

La tabla es el mismo, pero en DE es lógicamente no la tabla de origen de la tabla de destino Podría tener re-escrito 1) con una tabla de origen diferente, como otra tabla (física):

--script 3)
select *
into testDup
from TEST;

GO;

UPDATE Test SET Txt=(SELECT Txt FROM TestDUP WITH(NOLOCK) where ID=1) 
    WHERE ID=1

¿Por qué debería ser ignorado NOLOCK en otra mesa?
O, si está mal, pregunta entonces
Cómo escribir ACTUALIZACIÓN tener "indicios NOLOCK en la cláusula FROM que se aplican a la tabla de destino de una instrucción UPDATE o DELETE" porque incluso en 1) y 2) la tabla física es la misma, pero lógicamente la fuente (SELECCIONAR) mesa y objetivo (UPDATE) tabla son diferentes.

Cómo escribir una instrucción UPDATE que demuestra CON (NOLOCK) se ignora?
¿Por qué debe ser ignorada en absoluto? Se ignoró?
O, si se trata de una pregunta mal, entonces
¿Por qué la sintaxis permiten la pista que está garantizado para ser ignorado?

Una vez más, tampoco es imposible (o es?) Para escribir tal declaración una como está escrito en la documentación o que no entiendo el sentido de "ignora" (¿Cuál es el sentido de ignorarlo? O tenerlo en todos?) ...

Update2:
Las respuestas muestran que NOLOCK no es (actualiza) ignorado en la cláusula de la instrucción UPDATE lo que afirma docs BOL [1] A partir.
Pues bien, la esencia de esta pregunta: ¿
¿Me puede dar algún ejemplo (contexto) en la que haciendo caso omiso de NOLOCK en la cláusula FROM de la instrucción UPDATE hubiera tenido sentido?

[1] | Sugerencias de tabla (Transact-SQL)
SQL Server 2008 R2
http://msdn.microsoft.com/en-us/library/ms187373.aspx

¿Fue útil?

Solución

La cláusula FROM de una instrucción UPDATE o DELETE no es evidente en cualquiera de sus ejemplos. Que se tiene de cláusulas en subconsultas, pero los que no son la misma cosa.

Aquí hay una cláusula FROM para una actualización:

UPDATE t
SET Col = u.Val
FROM   /* <-- Start of FROM clause */
   Table t WITH (NOLOCK)
       inner join
   Table2 u
       on
          t.ID = u.ID
/* End of FROM clause */
WHERE
    u.Colx = 19

Y, como la documentación dice en voz alta, la WITH (NOLOCK) se tendrá en cuenta en este caso. En cuanto a por qué esto es permitido si va a ser ignorado, una conjetura sería que un indicio sería válida en la versión SELECT de la "misma" consulta, y la gente no SELECTs frecuencia de escritura (para asegurarse de que están dirigidas a la correcta filas / columnas), y luego vuelva a colocar la cláusula SELECT con un par UPDATE / SET de las cláusulas, y pueden dejar el resto de la consulta inalterada.


Actualización sobre la base de comentario / "respuesta" de vgv8:

Su actualización ejemplo, todavía no está mirando a la cláusula de la instrucción UPDATE FROM

La siguiente funciona bien, incluso con la TABLOCKX () abierta en la otra conexión:

UPDATE T  SET Txt= td.Txt
FROM TEST t inner join TESTDUP td  WITH (NOLOCK) on t.ID = td.ID
where t.ID = 1

Otros consejos

No se requiere adivinar.

Sybase y el uso del servidor de MS SQL una, el bloqueo de recursos 2PL automática interna, pero con el pleno cumplimiento de la norma ANSI SQL estándar ISO / IEC /. La sintaxis se pone tonta cuando intenta comprender todas las combinaciones posibles, porque algunas cláusulas no son relevantes para cada comando.

Lo que el manual está tratando de decir, pero no dice en Inglés sencillo, es:

  • para cualquier operación externa, o una sola consulta dentro de una transacción, que está realizando, puede SET ISOLATION LEVEL
  • que se pueden especificar utilizando UNCOMMITTED, NOLOCK, HOLDLOCKsyntax así
  • donde tiene uno IL en la consulta externa, o una sola consulta dentro de una transacción, pero desea utilizar un IL diferente para la consulta interna, que se puede hacer (uso de diferentes moduladores en la consulta interna)
  • por lo que podría tener una transacción de ejecución en IL-3, y tienen una SELECT dentro de ella la ejecución de al IL0 o IL-1

Por separado:

  • independientemente de lo que usted piensa que está haciendo, o desea realizar, ya que el bloqueo es automático, y ISOLATION LEVEL 3is requerida para UPDATES y DELETES, en READ UNCOMMITTED y NOLOCK no se aplican, y no se puede utilizar , si los ha utilizado el servidor ignorará

Después de haber creado y llenado 2 tablas idénticas de prueba y TestDUP [1], en una sola sesión (ventanas de SSMS) ejecuto

--2)
begin tran
Select Txt from TestDUP  with(TABLOCKX) 
WHERE ID=1
--rollback

que bloquea Selecciona de otra sesión (ventana de SSMS) en la misma mesa, por ejemplo:

 --3.1)
select * from TestDUP

pero no

 --3.2)
select * from TestDUP WITH(NOLOCK)

Tenga en cuenta que 3.1) está bloqueado, pero 3.2) no lo es.

Sin embargo, la actualización en otra prueba de la tabla usando SELECT desde TestDUP

--4)WITH(NOLOCK) is not honored until completing
-- (commit/roollback)-ing transaction 2)
UPDATE Test  SET Txt=
(Select Txt from TESTDUP WITH(NOLOCK)  where ID=1)
  WHERE ID=1;

está bloqueado debido CON (NOLOCK), en otra tabla de origen, se ignora en la cláusula FROM de la instrucción UPDATE.

Actualización:

--4.1)WITH(NOLOCK) is honored 
-- in FROM clause of UPDATE statement 
UPDATE Test  SET Txt= td.Txt
FROM TESTDUP td  WITH (NOLOCK)
where test.ID = 1 

--4.2) Note that without NOLOCK this script is blocked
-- until first transaction 2) completes (rollbacks or commits)
UPDATE Test  SET Txt= td.Txt
FROM TESTDUP td  WITH (NOLOCK)
where test.ID = 1  

Por lo tanto, ahora tiene sentido pero contradice a la documentación ya NOLOCK en la cláusula FROM de la instrucción UPDATE NO se tiene en cuenta, no es cierto?

[1] | Crear 2 mesas llenas de prueba de forma idéntica y testDUP:

if object_id('Test') IS not NULL
drop table Test;

CREATE TABLE Test (
  ID int IDENTITY PRIMARY KEY,
  Txt nvarchar(max) NOT NULL
)
GO
-----------
INSERT INTO Test
SELECT REPLICATE(CONVERT(nvarchar(max), 
     CHAR(65+ABS(CHECKSUM(NEWID()))%26)),100000)
GO 10

--COPYING TEST into TESTDUP with creating of the latter
select *
into testDup
from TEST;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top