it-swarm.com.de

SQL Server SELECT-Anweisungen, die zum Blockieren führen

Wir verwenden eine SQL Server 2005-Datenbank (keine Zeilenversionierung) mit einer großen select -Anweisung, und es wird gezeigt, dass andere Anweisungen nicht ausgeführt werden (gesehen mit sp_who2). Ich wusste nicht, dass SELECT-Anweisungen zu Blockierungen führen könnten - kann ich etwas dagegen tun?

16
Neil Barnwell

SELECT kann Updates blockieren. Ein ordnungsgemäß entworfenes Datenmodell und eine entsprechende Abfrage führen nur zu minimaler Blockierung und sind kein Problem. Der "übliche" WITH NOLOCK-Hinweis ist fast immer die falsche Antwort. Die richtige Antwort besteht darin, Ihre Abfrage so zu optimieren, dass keine großen Tabellen durchsucht werden.

Wenn die Abfrage nicht abgestimmt werden kann, sollten Sie zuerst die Option SNAPSHOT ISOLATION berücksichtigen. Zweitens sollten Sie DATABASE SNAPSHOTS verwenden. Die letzte Option sollte DIRTY READS sein (und es ist besser, die Isolationsstufe zu ändern als mit dem NOLOCK TIPP). Beachten Sie, dass Dirty Reads, wie der Name eindeutig besagt, inkonsistente Daten zurückgeben (z. B. kann Ihr Gesamtblatt unausgeglichen sein).

29
Remus Rusanu

Aus Dokumentation :

Mit Shared (S)-Sperren können gleichzeitige Transaktionen (SELECT) eine Ressource unter pessimistischer Parallelitätskontrolle lesen. Weitere Informationen finden Sie unter Types of Concurrency Control. Keine anderen Transaktionen können die Daten ändern, während shared (S) Sperren für die Ressource vorhanden sind. Shared (S)-Sperren für eine Ressource werden freigegeben, sobald der Lesevorgang abgeschlossen ist, es sei denn, die Transaktionsisolationsstufe ist auf wiederholbares Lesen oder höher eingestellt oder ein Sperrhinweis wird verwendet, um die shared (S)-Sperren für die Dauer der Transaktion beizubehalten.

Ein shared lock ist mit einer anderen gemeinsam genutzten Sperre oder einer Aktualisierungssperre kompatibel, jedoch nicht mit einer Exklusivsperre.

Das bedeutet, dass Ihre SELECT-Abfragen UPDATE- und INSERT-Abfragen blockieren und umgekehrt.

Eine SELECT-Abfrage setzt eine temporäre gemeinsam genutzte Sperre ein, wenn sie einen Werteblock aus der Tabelle liest, und entfernt sie, wenn das Lesen abgeschlossen ist.

Während der Zeit, in der die Sperre besteht, können Sie nichts mit den Daten im gesperrten Bereich tun.

Zwei SELECT-Abfragen blockieren sich niemals (es sei denn, sie sind SELECT FOR UPDATE)

Sie können die Isolationsstufe SNAPSHOT für Ihre Datenbank aktivieren und verwenden. Beachten Sie jedoch, dass UPDATE-Abfragen nicht durch SELECT-Abfragen gesperrt werden können (was anscheinend Ihr Fall ist).

Dies verhindert jedoch, dass SELECT-Abfragen durch UPDATE gesperrt werden.

Beachten Sie außerdem, dass SQL Server im Gegensatz zu Oracle den Sperren-Manager verwendet und die Sperren in einer verknüpften Liste im Arbeitsspeicher speichert.

Das bedeutet, dass die bloße Tatsache des Platzierens und Entfernens einer Sperre unter hoher Last langsam sein kann, da die verknüpfte Liste selbst vom Transaktionsthread gesperrt werden sollte.

14
Quassnoi

Um fehlerhafte Lesevorgänge durchzuführen, können Sie entweder:

 using (new TransactionScope(TransactionScopeOption.Required, 
 new TransactionOptions { 
 IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
 {
 //Your code here
 }

oder

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."

denken Sie daran, dass Sie WITH (NOLOCK) nach jeder zu schreibenden Tabelle schreiben müssen

2
David Espart

Sie könnten auch Deadlocks bekommen:

"Deadlocks, an denen nur eine Tabelle beteiligt ist" http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

und oder falsche Ergebnisse:

Msgstr "Wählt unter READ COMMITTED und REPEATABLE READ möglicherweise falsche Ergebnisse aus."

http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return-incorrect-results.aspx

0
A-K

Sie können den Tabellenhinweis WITH(READPAST) verwenden. Es unterscheidet sich von der WITH(NOLOCK). Die Daten werden vor dem Start der Transaktion abgerufen und niemand wird blockiert. Stellen Sie sich vor, Sie haben die Anweisung ausgeführt, bevor die Transaktion gestartet wurde.

SELECT * FROM table1  WITH (READPAST)
0
Senol Cakir

Sie können für die Transaktionsebene Read Uncommitted festlegen

0
Johnno Nolan