Perché NOLOCK viene ignorato “nella clausola FROM che si applicano alla tabella di destinazione di un'istruzione UPDATE o DELETE”?

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

Domanda

Sono confuso con la frase BOL:

  

"READUNCOMMITTED e NOLOCK non possono essere specificati per le tabelle modificate da inserimento, aggiornamento o di operazioni di eliminazione. Lo SQL Server Query Optimizer ignora i suggerimenti READUNCOMMITTED e NOLOCK nella clausola FROM che si applicano alla tabella di destinazione di un'istruzione UPDATE o DELETE" [1]

Ad esempio, se scrivo

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

viene eseguito senza errori (o avvisi) ed è probabilmente 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;

che è anche eseguito senza errori o avvisi.
E 'equivalente?

Il tavolo è lo stesso, ma in FROM è logicamente la tabella di origine non è la tabella di destinazione Potrei avere riscritto 1) con una tabella di origine diversa da un'altra tabella (fisica):

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

GO;

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

Perché NOLOCK essere ignorato su un altro tavolo?
Oppure, se è sbagliato, domanda allora
Come scrivere UPDATE avere "suggerimenti NOLOCK nella clausola FROM che si applicano alla tabella di destinazione di un'istruzione UPDATE o DELETE" perché anche in 1) e 2) la tabella fisica è lo stesso, ma logicamente la fonte (in SELEZIONATE) tavolo e di destinazione (in UPDATE) tabella sono diversi.

Come scrivere un dimostrando istruzione UPDATE che CON (NOLOCK) viene ignorato?
Perché dovrebbe essere ignorato a tutti? E 'ignorato?
O, se si tratta di una domanda sbagliata, allora
Perché sintassi permettono il suggerimento che è garantito per essere ignorato?

Ancora una volta, o è impossibile (o è?) Di scrivere tale dichiarazione una come scritto nella documentazione o non capisco il senso di "ignora" (Che cosa è il senso di ignorarlo? O per averlo a tutti?) ...

UPDATE2:
Le risposte mostrano che NOLOCK non è (aggiornato) ignorato nella clausola FROM di un'istruzione UPDATE ciò che viene affermato dai documenti BOL [1].
Ebbene, l'essenza di questa domanda:
Mi può dare qualche esempio (contesto) in cui ignorando di NOLOCK nella clausola FROM di un'istruzione UPDATE avrebbe avuto senso?

[1]
Hint di tabella (Transact-SQL)
SQL Server 2008 R2
http://msdn.microsoft.com/en-us/library/ms187373.aspx

È stato utile?

Soluzione

La clausola FROM di un'istruzione UPDATE o DELETE non è evidente in uno dei tuoi esempi. Hai da clausole sottoquery, ma questi non sono la stessa cosa.

Ecco una clausola FROM per un aggiornamento:

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

E, come la documentazione chiama fuori, l'WITH (NOLOCK) viene ignorato in questo caso. Per quanto riguarda il motivo per cui questo è consentito se sta andando ad essere ignorato, un'ipotesi è che un tale suggerimento sarebbe valida nella versione SELECT della "stessa" interrogazione, e la gente SELECT frequente di scrittura (per assicurare che stanno targeting e la correttezza righe / colonne) e quindi sostituire la clausola SELECT con un paio UPDATE / SET di clausole, e può lasciare il resto della query inalterato.


Aggiornamento sulla base di commento / "risposta" da vgv8:

Il tuo aggiornamento esempio ancora non sta guardando a clausola FROM dell'istruzione UPDATE

Di seguito funziona bene, anche con la TABLOCKX () aperto dall'altro collegamento:

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

Altri suggerimenti

senza l'ipotesi richiesto.

Sybase e l'uso server MS SQL uno interno, bloccaggio automatico delle risorse 2PL, ma con piena conformità con la norma ISO / IEC / ANSI SQL standard. La sintassi ottiene sciocco quando si tenta di capire tutte le combinazioni possibili, perché alcune clausole non sono rilevanti per ogni comando.

Quello che il manuale sta cercando di dire, ma non dice in inglese semplice, è:

  • per qualsiasi operazione esterno, o una singola query all'interno di una transazione, si sta eseguendo, è possibile SET ISOLATION LEVEL
  • che può essere specificato utilizzando UNCOMMITTED, NOLOCK, HOLDLOCKsyntax così
  • dove si dispone di una IL nella query esterna, o una singola query all'interno di una transazione, ma desidera utilizzare un IL diverso per la query interna, che può essere fatto (utilizzare diversi modulatori sulla query interna)
  • così si potrebbe avere una transazione in esecuzione a IL3, e hanno una SELECT all'interno di esso eseguire al IL0 o IL1

Separatamente:

  • indipendentemente da ciò che si pensa che si sta facendo, o vuoi fare, dal momento che il blocco è automatico, e ISOLATION LEVEL 3is richiesta per UPDATES e DELETES, in cui READ UNCOMMITTED e NOLOCK non si applicano, e non può essere utilizzato , se li avete utilizzato il server li ignorerà

Dopo aver creato e riempito 2 tavoli identici test e TestDUP [1], in una sessione (finestre di SSMS) eseguo

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

che blocca selezionare dalla finestra un altro (SQL Server Management Studio) della sessione sullo stesso tavolo, per esempio:

 --3.1)
select * from TestDUP

, ma non

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

Si noti che 3.1) è bloccato, ma 3.2) non lo è.

Anche se, l'aggiornamento su un altro TEST tabella utilizzando SELECT da 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;

è bloccato a causa CON (NOLOCK), su un altro tavolo di origine, viene ignorato nella clausola FROM di UPDATE.

Aggiornamento:

--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  

Quindi, ora ha un senso, ma contraddice la documentazione dal NOLOCK nella clausola FROM di un'istruzione UPDATE NON viene ignorato, non è vero?

[1]
Crea 2 tavoli in modo identico pieni di prova e 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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top