Es hat eine große Auswirkung.
Die Update-Sperre erfordert eine Update-Sperre für die Zeile, eine Intent-Aktualisierung auf der Seite und eine gemeinsame Sperre für die Tabelle/Datenbank.
Das hindert andere Abfragen nicht daran, auf die Daten innerhalb der Tabelle zuzugreifen, da die Sperren auf der Seite/Datenbank reine Freigabe-Sperren sind. Sie können Sperren nur nicht gegen die einzelne Zeile/Seite/Tabelle stoßen, indem Sie versuchen, eine Operation auszuführen, die Sperren widerspricht. Wenn dies der Fall wäre, würde die Anfrage hinter den aktuellen Sperren in die Warteschlange gestellt und darauf warten, dass sie verfügbar wird, bevor sie fortfahren kann.
Mit Hilfe von Holdlock wird die Abfrage serialisiert und die Tabelle wird ausschließlich gesperrt, bis die Aktion abgeschlossen ist. Dies verhindert, dass jemand die Tabelle liest, es sei denn, der Nolock-Hinweis wird verwendet, was ein potenziell schmutziges Lesen ermöglicht.
Um den Effekt zu sehen, erstellen Sie eine Beispieltabelle 'foo' und fügen Sie einige Daten in den Papierkorb ein.
begin tran
select * from foo with (updlock)
where tableid = 1
-- notice there is no commit tran
öffnen ein weiteres Fenster und versuchen:
select * from foo
Die Reihen zurückkommen, begehen nun die ursprüngliche Abfrage-Transaktion. Re-run es verändert auch die Verwendung holdlock:
begin tran
select * from foo with (updlock, holdlock)
where tableid = 1
in das andere Fenster Gehen Sie zurück und versuchen, die Daten erneut auswählen, wird die Abfrage nicht Werte zurückgeben, da es durch die exklusive Sperre blockiert wird. Übernehmen Sie die Transaktion im ersten Fenster und die Ergebnisse in der zweiten Abfrage werden angezeigt, da sie nicht mehr blockiert sind.
Abschließender Test ist die Verwendung der Nolock, führen Sie die Transaktion erneut mit Hilfe von Update und Holdlock. dann läuft nach der im zweiten Fenster:
select * from foo (nolock)
Die Ergebnisse kommen wieder automatisch, da Sie das Risiko einer schmutzigen Lese angenommen haben (lesen Sie uncommitted).
Es hat also einen großen Einfluss darauf, dass Sie Aktionen gegen diese Tabelle zur Serialisierung erzwingen, was Sie wünschen (abhängig von der durchgeführten Aktualisierung) oder einen sehr großen Engpass in dieser Tabelle erzeugen . Wenn dies bei einer ausgelasteten Tabelle mit lang laufenden Transaktionen der Fall wäre, würde dies zu erheblichen Verzögerungen innerhalb einer Anwendung führen.
Wie bei allen SQL-Funktionen können sie bei richtiger Verwendung sehr leistungsfähig sein, aber die falsche Verwendung eines Features/Hinweises kann zu erheblichen Problemen führen. Ich ziehe es vor, Hinweise als letzte Möglichkeit zu verwenden, wenn ich die Engine außer Kraft setzen muss - nicht als Standardansatz.
Bearbeiten als angefordert: Getestet in SQL 2005, 2008, 2008R2 (Alle Unternehmen) - alle auf ziemlich viele Standardeinstellungen installiert, Test-Datenbank erstellt mit allen Standardeinstellungen (nur den Namen der DB eingegeben).
große antwort, danke – marijne
nette erklärung, das hilft sehr! – Mercurybullet
@Darren - Ich habe die von Ihnen vorgenommene Änderung rückgängig gemacht, keine Sperre ist nicht die Standardeinstellung und die zweite Auswahl sollte keine Update-Sperre übernehmen. – Andrew