Warum NOLOCK wird ignoriert „in der FROM-Klausel, die in die Zieltabelle einer UPDATE oder DELETE-Anweisung anwenden“?

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

Frage

Ich bin von der BOL Satz verwirrt:

  

„READUNCOMMITTED und NOLOCK nicht für Tabellen einfügen, aktualisieren oder Löschvorgänge geändert angegeben werden. Der SQL-Server-Abfrageoptimierer ignoriert die READUNCOMMITTED und NOLOCK Hinweise in der FROM-Klausel, die in die Zieltabelle einer UPDATE oder DELETE-Anweisung anwenden“ [1]

Zum Beispiel, wenn ich schreibe

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

wird es ohne Fehler (oder Warnungen) laufen und ist wahrscheinlich äquivalent zu

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

, die auch ohne Fehler oder Warnungen ausgeführt wird.
Ist es gleichwertig?

In der Tabelle ist das gleiche, aber in FROM ist es logisch die Quelltabelle nicht die Zieltabelle Ich könnte neu geschrieben 1) mit einer anderen Quelltabelle als ein anderen (physische) Tabelle habe:

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

GO;

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

Warum sollte NOLOCK auf einem anderen Tisch ignoriert werden?
Oder, wenn es falsch ist, dann Frage
Wie UPDATE schreiben „NOLOCK Hinweise in dem FROM-Klausel, die in die Zieltabelle eines UPDATE oder DELETE-Anweisung anwenden“ hat, weil auch in 1) und 2) die physische Tabelle ist die gleiche, aber logisch die Quelle (in SELECT) Tabelle und Ziel (in UPDATE) Tabelle sind verschiedene.

Wie eine UPDATE-Anweisung Demonstrieren zu schreiben, die mit (NOLOCK) ignoriert wird?
Warum sollte es überhaupt ignoriert werden? Ist es ignoriert?
Oder, wenn es sich um eine falsche Frage, dann
Warum erlauben Syntax den Hinweis, die garantiert wird ignoriert werden?

Wieder einmal ist es entweder unmöglich (oder ist es?), So eine Erklärung zu schreiben, wie es in der Dokumentation geschrieben oder verstehe ich nicht das Gefühl der „ignoriert“ (Was das Gefühl, es zu ignorieren ist? Oder es zuzumin alle?) ...

UPDATE2:
Die Antworten zeigen, dass NOLOCK nicht (aktualisiert) ignoriert in der FROM-Klausel der UPDATE-Anweisung, welche von BOL docs behauptet wird [1].
Nun, das Wesen dieser Frage:
Können Sie mir kein Beispiel (Kontext), wo in der NOLOCK ignoriert FROM-Klausel der UPDATE-Anweisung Sinn gemacht hätte?

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

War es hilfreich?

Lösung

Die FROM-Klausel einer UPDATE oder DELETE-Anweisung ist in jedem Ihrer Beispiele nicht ersichtlich. Sie haben von Klauseln in Unterabfragen, aber das ist nicht die gleiche Sache.

Hier ist eine FROM-Klausel für eine UPDATE:

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

Und, wie die Dokumentation ruft, wird die WITH (NOLOCK) in diesem Fall ignoriert. Wie, warum dies zulässig ist, wenn sie ignoriert werden wird, würde man vermuten, dass ein solcher Hinweis in der SELECT Version der „gleichen“ Abfrage gültig ist, und die Leute haben häufig Schreib SELECTs (um sicherzustellen, sie sind Targeting die richtige Zeilen / Spalten), und ersetzen Sie dann die SELECT Klausel mit einem UPDATE / SET Paar von Klauseln und können den Rest der Abfrage unverändert lassen.


aktualisiert, basierend auf Kommentar / "Antwort" von vgv8:

Ihr Beispiel Update noch nicht betrachtet das FROM-Klausel der UPDATE-Anweisung

Die folgende funktioniert gut, auch mit dem TABLOCKX () offen auf der anderen Verbindung:

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

Andere Tipps

Keine erforderlich Erraten.

Sybase und MS SQL Server verwenden eine interne, automatische 2PL Ressource sperren, aber mit voller Übereinstimmung mit der ISO / IEC / ANSI SQL-Standard. Die Syntax wird dumm, wenn Sie versuchen, alle möglichen Kombinationen zu verstehen, weil einige Klauseln für jeden Befehl nicht relevant sind.

Was das Handbuch versucht zu sagen, aber nicht sagen, in einfachem Englisch, ist:

  • für jede Art Außenbetrieb, oder eine einzelne Abfrage innerhalb einer Transaktion, die Sie durchführen, können Sie SET ISOLATION LEVEL
  • , die angegeben werden können UNCOMMITTED, NOLOCK, HOLDLOCKsyntax mit als auch
  • , wo Sie eine IL in der äußeren Abfrage haben oder eine einzelne Abfrage innerhalb einer Transaktion, wollen aber ein anderen IL für die innere Abfrage verwenden, die (Verwendung verschiedene Modulatoren auf der inneren Abfrage) durchgeführt werden können
  • , so dass Sie eine Transaktion auf IL3 haben könnte ausführen, und haben eine SELECT innerhalb es bei IL0 oder IL-1
  • Ausführen

Getrennt:

  • unabhängig davon, was Sie denken, Sie tun oder tun wollen, da die Verriegelung automatisch, und ISOLATION LEVEL 3is erforderlich für UPDATES und DELETES, wobei READ UNCOMMITTED und NOLOCK nicht anwenden, und kann nicht verwendet werden , wenn man sich der Server sich ignoriert verwendet hat

Nachdem erstellt und gefüllt 2 identischen Tabellen-Test und TestDUP [1], in einer Sitzung (Fenstern von SSMS) I

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

, die Blöcke aus einer anderen Sitzung SELECT (SSMS Fenster) auf der gleichen Tabelle, zum Beispiel:

 --3.1)
select * from TestDUP

aber nicht

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

Beachten Sie, dass 3.1) blockiert ist, aber 3.2) nicht.

Obwohl, auf einem anderen Tabelle TEST Aktualisierung mit SELECT aus 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;

blockiert, weil WITH (NOLOCK), auf einer anderen Quelltabelle, in FROM-Klausel von UPDATE-Anweisung ignoriert.

Update:

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

So ist es nun sinnvoll, aber es widerspricht der Dokumentation seit NOLOCK in FROM-Klausel von UPDATE-Anweisung nicht außer Acht gelassen wird, ist es nicht?

[1]
Erstellen 2 identisch gefüllten Tabellen-Test und 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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top