Verursacht eine erhöhte Netzwerklatenz in MS SQL Server Tabellensperren?


16

Wenn ich eine SQL Server-Datenbank über ein Netzwerk mit hoher Latenz einzeln aufrufe, treten aufgrund dieser Latenz Tabellensperren auf? Angenommen, ich frage Tabelle A nach einigen Datensätzen ab, und SQL Server muss diese Daten über ein langsames Netzwerk zurückgeben. Besteht eine Lesesperre für Tabelle A, während der Server die Antwort über das Netzwerk sendet, oder gibt SQL Server die Sperre vor dem Senden frei die Antwort?

Würde die Antwort auch je nach Größe der Antwort variieren? Wenn es nur ein paar KB gegenüber mehreren hundert MB zurückgeben muss, würde das einen Unterschied machen?

Das Erstellen einer expliziten Transaktion, das Ausführen von Abfragen und das Schließen der Transaktion würde offensichtlich dazu führen, dass die Tabellen gesperrt werden, da die Dauer der Transaktion mit meiner Latenz korreliert.


Wenn Sie keinen nolockHinweis angeben , wird immer eine Sperre angezeigt . Die Latenz bestimmt nur, wie lange die Sperre gehalten wird.
Brandon

3

@brandon Wird das irgendwo von Microsoft dokumentiert? Meine Suchanfragen sind leer.
Evan M

1
@Brandon NOLOCK bedeutet nicht, was Sie denken, dass es bedeutet.
Aaron Bertrand

3
@Brandon Unless you specify a nolock hint, there will always be a lock.<- Dies impliziert, dass bei Verwendung von nolock möglicherweise keine Sperren vorhanden sind. Ich habe nur geklärt.
Aaron Bertrand

Antworten:


15

Wenn der Client lange Zeit zum Empfangen von Daten benötigt und dann eine Bestätigung an SQL Server sendet, dass er die Daten empfangen hat, die SQL Server warten muss, gibt SQL Server aufgrund dieser Wartezeit die von der Abfrage gehaltenen Sperren nur dann frei, wenn eine Bestätigung vom Client eingeht.

Dies ist nicht genau, es hängt von der Isolationsstufe ab.

Standardmäßig READ COMMITTEDwerden für die Dauer der Anweisungsausführung keine Sperren gehalten. READ COMMITTEDKeine Lesekonsistenz auf Anweisungsebene. Die einzige Garantie besteht darin, dass Sie keine nicht festgeschriebenen Daten lesen können. Eine gemeinsam genutzte Sperre wird erfasst und gehalten, um die Zeile zu lesen, und dann freigegeben.

Es sei denn, Sie haben LOB-Typen.

LOB-Typen, die möglicherweise sehr groß sind, können nicht gepuffert werden. Eine gemeinsam genutzte Sperre muss erworben und gehalten werden, bis die Anweisung vollständig ist, was im Wesentlichen zu einem REPEATABLE READVerhalten bei führt READ COMMITTED.

Wenn ich eine MSSQL-Datenbank über ein Netzwerk mit hoher Latenz einzeln aufrufe, treten aufgrund dieser Latenz Tabellensperren auf?

Die Latenz verursacht nicht die Tabellensperre, nein. Wenn jedoch eine Tabellensperre erworben wurde, wird diese durch die Latenz verlängert.

Um jemanden zu zitieren, der die Mechanik besser kennt als ich ( @RemusRusanu ):

Die Ergebnisse werden im Verlauf der Ausführung an das Client-Programm zurückgegeben. Wenn Zeilen den Ausführungsbaum sprudeln lassen, muss der Top-Operator diese Zeilen normalerweise in Netzwerkpuffer schreiben und an den Client zurücksenden. Das Ergebnis wird nicht zuerst in einem Zwischenspeicher (Speicher oder Datenträger) erstellt und dann an den Client zurückgesendet, sondern beim Erstellen (während der Ausführung der Abfrage) zurückgesendet. Das Zurücksenden des Ergebnisses an den Client unterliegt natürlich dem Netzwerkflusssteuerungsprotokoll. Wenn der Client das Ergebnis nicht aktiv konsumiert (z. B. durch Aufrufen von SqlDataReader.Read ()), muss die Ablaufsteuerung die sendende Seite (die gerade ausgeführte Abfrage) sperren, und dies wiederum setzt die Ausführung von aus Abfrage.[Quelle]

Wenn die Ergebnisse nicht so schnell verbraucht werden, wie SQL Server sie liefern kann, sei es aufgrund des Clients oder des Netzwerks, ASYNC_NETWORK_IOhäufen sich die Wartezeiten. Dies hat, um es noch einmal zu wiederholen, keinen Einfluss auf die erworbenen Sperren, sondern nur auf die Dauer, für die sie gehalten werden.


9

Die Antwort von Mark hat viel von meiner Verwirrung beseitigt, aber ich wollte meine Ergebnisse veröffentlichen, nachdem ich dies mit NetBalancer getestet hatte, um die Latenz zu emulieren.

Ich ließ meinen lokalen Computer einen Remote-SQL-Server aufrufen und in einer kleinen Transaktion sowohl SELECT- als auch INSERT-Anweisungen für eine Tabelle ausführen. Auf dem Remotecomputer stellte ich eine Verbindung zur lokalen SQL-Instanz her und durchlief die Tabelle sys.dm_tran_locks wiederholt mit einer WHILE-Schleife, um nach Sperren für die Tabelle zu suchen, die ich geändert und aus der ich gelesen habe. Ich habe NetBalancer auf dem Server installiert und damit die Netzwerklatenz für die Netzwerkverbindung des Servers emuliert.

Folgendes habe ich gefunden:

  • Bei Anweisungen, die nicht viele Daten an den Client zurückgeben, hat die Latenz keine Auswirkung auf das Sperren. Ich habe höchstens ein paar hundert Byte Daten zurückgegeben. Die Transaktion auf meinem Computer hatte eine Wartezeit von 250 ms, in der die Sperren beibehalten wurden, und als ich die Netzwerklatenz auf 5000 ms erhöhte, blieb die Sperrdauer in der Nähe von 250 ms.
  • Bei Anweisungen, die viele Daten zurückgeben, wirkt sich die Latenz definitiv auf das Sperren aus. Ich habe Zehntausende von Zeilen an den Client zurückgegeben, und ohne Latenz war die Sperrdauer kurz. Wenn ich die Latenz erhöhte, wurden die Sperren fortgesetzt, bis ich alle Daten erhalten hatte.

Daraus schließe ich, dass die Latenz keine Rolle spielt, solange die Daten in den Netzwerkpuffer passen. Wenn SQL viele Daten im Netzwerkpuffer ablegen muss, führt die Latenz dazu, dass dieser Puffer gesichert wird, und SQL speichert die Tabellensperren, bis das gesamte Abfrageergebnis im Puffer abgelegt werden kann.


Interessante Ergebnisse. Mit welchem ​​Client-Programm / welcher Bibliothek ist das?
James L

Gutes Zeug. Gibt es eine Chance, dass Sie ein bisschen mehr Zeit damit verbringen können, um zu sehen, ob Sie die Ergebnisgröße bestimmen können, bei der dies auftritt?
Mark Storey-Smith

@ MarkStorey-Smith Ich glaube nicht, dass ich einen genauen Wert erhalten kann, und er würde zweifellos von Maschine zu Maschine variieren. Aus vircom.com/security/improve-sql-nic-performance geht hervor , dass es sich um eine Einstellung auf Ihrer lokalen Netzwerkkarte handelt. Die Einstellung auf meinem Datenbankserver wurde auf "auto" festgelegt
Evan M,

@ James Ich habe gerade SSMS auf beiden Maschinen verwendet
Evan M

0

Wenn ich eine MSSQL-Datenbank über ein Netzwerk mit hoher Latenz einzeln aufrufe, treten aufgrund dieser Latenz Tabellensperren auf?

Wenn eine Abfrage von SQL Server ausgelöst und abgeschlossen wird, werden die Ergebnisse erstellt. Legen Sie sie in den Ausgabepuffer und senden Sie sie an den Client, der dann das Ergebnis aus dem Ausgabepuffer abruft. SQL Server gibt die von der Abfrage gehaltenen Sperren nur dann frei, wenn eine Bestätigung vom Client eingeht. Dies kann zu Blockierungen führen.

Bearbeiten: Evan Sie können auf diesen MS-Support-Artikel verweisen

In Abschnitt 3

Durch eine SPID verursachte Blockierung, deren entsprechende Clientanwendung nicht alle Ergebniszeilen vollständig abgerufen hat

Nach dem Senden einer Abfrage an den Server müssen alle Anwendungen alle Ergebniszeilen sofort vollständig abrufen. Wenn eine Anwendung nicht alle Ergebniszeilen abruft, können Sperren in den Tabellen verbleiben, die andere Benutzer blockieren. Wenn Sie eine Anwendung verwenden, die SQL-Anweisungen transparent an den Server sendet, muss die Anwendung alle Ergebniszeilen abrufen. Wenn dies nicht der Fall ist (und dies nicht konfiguriert werden kann), können Sie das Blockierungsproblem möglicherweise nicht beheben. Um das Problem zu vermeiden, können Sie schlecht verhaltene Anwendungen auf eine Berichterstellungs- oder Entscheidungsunterstützungsdatenbank beschränken.


Danke für deine Antwort Shanky! Wissen Sie zufällig, ob dies irgendwo dokumentiert ist?
Evan M


5
Das ist nicht richtig.
Mark Storey-Smith

Dies ist richtig, es scheint, dass die Anwendung nicht alle Ergebniszeilen abruft. Es können Sperren in den Tabellen verbleiben, die andere Benutzer blockieren. Wenn Sie eine Anwendung verwenden, die SQL-Anweisungen transparent an den Server sendet, muss die Anwendung alle Ergebniszeilen abrufen. Wenn dies nicht der Fall ist (und dies nicht konfiguriert werden kann), können Sie das Blockierungsproblem möglicherweise nicht beheben. Um das Problem zu vermeiden, können Sie schlecht verhaltene Anwendungen auf eine Berichterstellungs- oder Entscheidungsunterstützungsdatenbank beschränken. ' Außerdem habe ich allgemein gesprochen. Sie können hier lesen support2.microsoft.com/kb/224453
Shanky

4
@Shanky Erstellen Sie eine große Tabelle. SELECT *davon in an READ COMMITTEDin einer SSMS Verbindung, Monitor Schlösser von einem anderen. Wie viele Schlösser sehen Sie zu irgendeinem Zeitpunkt?
Mark Storey-Smith
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.