Ein SELECT
in SQL Server platziert eine gemeinsame Sperre für eine Tabellenzeile - und eine zweite SELECT
würde auch eine gemeinsame Sperre erfordern, und diese sind miteinander kompatibel.
Also nein - einer SELECT
kann keinen anderen blockieren SELECT
.
Der WITH (NOLOCK)
Abfragehinweis wird verwendet, um Daten lesen zu können, die gerade eingefügt werden (durch eine andere Verbindung) und die noch nicht festgeschrieben wurden.
Ohne diesen Abfragehinweis SELECT
kann das Lesen einer Tabelle durch eine fortlaufende INSERT
(oder UPDATE
) Anweisung blockiert werden, die Zeilen (oder möglicherweise eine ganze Tabelle) exklusiv sperrt, bis die Transaktion dieser Operation festgeschrieben (oder zurückgesetzt) wurde.
Das Problem des WITH (NOLOCK)
Hinweises ist: Möglicherweise lesen Sie am Ende Datenzeilen, die überhaupt nicht eingefügt werden (wenn die INSERT
Transaktion zurückgesetzt wird). In Ihrem z. B. Bericht werden möglicherweise Daten angezeigt, die nie wirklich in die Datenbank übernommen wurden .
Es gibt einen weiteren Abfragehinweis, der nützlich sein könnte - WITH (READPAST)
. Dies weist den SELECT
Befehl an, nur alle Zeilen zu überspringen, die er zu lesen versucht und die ausschließlich gesperrt sind. Das SELECT
wird nicht blockiert und es werden keine "schmutzigen" nicht festgeschriebenen Daten gelesen - es werden jedoch möglicherweise einige Zeilen übersprungen, z. B. werden nicht alle Zeilen in der Tabelle angezeigt.
SELECT
Abfragen) geben, dieWITH (NOLOCK)
ohne Grund verwendet werden könnten?Bei der Leistung konzentrieren Sie sich weiterhin auf die Auswahl.
Shared blockiert keine Lesevorgänge.
Aktualisierung der freigegebenen Sperrblöcke.
Wenn Sie Hunderte von gemeinsam genutzten Sperren haben, dauert es eine Weile, bis eine exklusive Sperre vorliegt, da gewartet werden muss, bis die freigegebenen Sperren gelöscht sind.
Standardmäßig nimmt eine Auswahl (Lesen) eine gemeinsame Sperre.
Gemeinsame (S) Sperren ermöglichen gleichzeitigen Transaktionen das Lesen (SELECT) einer Ressource.
Eine gemeinsame Sperre, die sich nicht auf andere Auswahlen auswirkt (1 oder 1000).
Der Unterschied besteht darin, wie der Nolock- oder der Shared-Lock-Effekt aktualisiert oder eingefügt werden.
Keine anderen Transaktionen können die Daten ändern, solange gemeinsam genutzte (S) Sperren für die Ressource vorhanden sind.
Eine gemeinsame Sperre blockiert ein Update!
Nolock blockiert jedoch kein Update.
Dies kann enorme Auswirkungen auf die Leistung von Updates haben. Es wirkt sich auch auf Einsätze aus.
Dirty Read (Nolock) klingt einfach schmutzig. Sie werden niemals Teildaten erhalten. Wenn ein Update John in Sally ändert, werden Sie niemals Jolly bekommen.
Ich verwende häufig gemeinsam genutzte Sperren für die Parallelität. Daten sind veraltet, sobald sie gelesen werden. Eine Lektüre von John, die in der nächsten Millisekunde zu Sally wechselt, sind veraltete Daten. Eine Lektüre von Sally, die John in der nächsten Millisekunde zurückgesetzt wird, sind veraltete Daten. Das ist im Millisekundenbereich. Ich habe einen Datenlader, dessen Ausführung 20 Stunden dauert, wenn Benutzer gemeinsam genutzte Sperren verwenden, und dessen Ausführung 4 Stunden dauert, wenn Benutzer keine Sperren verwenden. Gemeinsame Sperren führen in diesem Fall dazu, dass die Daten 16 Stunden veraltet sind.
Verwenden Sie keine falschen Nolocks. Aber sie haben einen Platz. Wenn Sie einen Scheck schneiden möchten, wenn ein Byte auf 1 gesetzt ist, und ihn dann auf 2 setzen, wenn der Scheck geschnitten wird - keine Zeit für einen Nolock.
quelle
Ich muss einen wichtigen Kommentar hinzufügen. Jeder erwähnt, dass
NOLOCK
nur schmutzige Daten gelesen werden. Das ist nicht genau. Es ist auch möglich, dass Sie dieselbe Zeile zweimal erhalten oder die gesamte Zeile beim Lesen übersprungen wird. Der Grund dafür ist, dass Sie möglicherweise gleichzeitig nach Daten fragen, wenn SQL Server den B-Baum neu ausbalanciert.Überprüfen Sie andere Threads
https://stackoverflow.com/a/5469238/2108874
http://www.sqlmag.com/article/sql-server/quaere-verum-clustered-index-scans-part-iii.aspx )
quelle
Bei meiner Arbeit haben wir ein sehr großes System, das auf vielen PCs gleichzeitig läuft, mit sehr großen Tabellen mit Hunderttausenden von Zeilen und manchmal vielen Millionen Zeilen.
Wenn Sie ein SELECT für eine sehr große Tabelle vornehmen, möchten Sie beispielsweise wissen, dass jede Transaktion, die ein Benutzer in den letzten 10 Jahren durchgeführt hat, und der Primärschlüssel der Tabelle nicht effizient erstellt wurde. Die Abfrage kann einige Minuten dauern laufen.
Dann kann unsere Anwendung auf vielen PCs eines Benutzers gleichzeitig ausgeführt werden und auf dieselbe Datenbank zugreifen. Wenn also jemand versucht, in die Tabelle einzufügen, die der andere SELECT liest (auf Seiten, die SQL zu lesen versucht), kann ein LOCK auftreten und die beiden Transaktionen blockieren sich gegenseitig.
Wir mussten unserer SELECT-Anweisung ein "NO LOCK" hinzufügen, da es sich um ein riesiges SELECT auf einer Tabelle handelte, die von vielen Benutzern gleichzeitig häufig verwendet wird, und wir hatten die ganze Zeit LOCKS.
Ich weiß nicht, ob mein Beispiel klar genug ist? Dies ist ein Beispiel aus dem wirklichen Leben.
quelle
Das
SELECT WITH (NOLOCK)
ermöglicht es liest von unbestätigten Daten, die mit der ÄquivalentREAD UNCOMMITTED
Isolationsstufe auf Ihrer Datenbank. DasNOLOCK
Schlüsselwort ermöglicht eine feinere Steuerung als das Festlegen der Isolationsstufe für die gesamte Datenbank.Wikipedia hat einen nützlichen Artikel: Wikipedia: Isolation (Datenbanksysteme)
Es wird auch ausführlich in anderen Stackoverflow-Artikeln besprochen.
quelle
READUNCOMMITTED
(ein Alias fürNOLOCK
), wenn dies ein gültiger Anwendungsfall ist. Dadurch wird die tatsächliche Operation, die nicht wirklich "ohne Sperren" ist, weniger unklar.Ohne Sperre auswählen - Wählt Datensätze aus, die möglicherweise eingefügt werden oder nicht. Sie werden schmutzige Daten lesen.
Beispiel: Nehmen wir an, eine Transaktion fügt 1000 Zeilen ein und schlägt dann fehl.
Wenn Sie auswählen, erhalten Sie die 1000 Zeilen.
quelle