Frage

Wir verwenden eine SQL Server 2005-Datenbank (keine Zeilenversionsverwaltung) mit einer großen select-Anweisung, und wir sehen es andere Aussagen blockieren läuft (mit sp_who2 gesehen). Ich wusste nicht, SELECT-Anweisungen dazu führen könnten, blockiert - gibt es etwas, was ich tun kann, dies zu mildern

War es hilfreich?

Lösung

SELECT können Updates blockieren. Ein richtig entworfenes Datenmodell und Abfrage wird nur eine minimale Blockierung verursachen und kein Problem sein. Die ‚übliche‘ MIT NOLOCK-Hinweis ist fast immer die falsche Antwort. Die richtige Antwort ist, stimmen Sie Ihre Abfrage, damit es nicht riesige Tabellen scannt.

Wenn die Abfrage ist untunable dann sollten Sie zunächst prüfen, Snapshot-Isolationsstufe , die zweite sollten Sie DATABASE SNAPSHOTS und letzte Option sollte DIRTY sein mit berücksichtigen READS (und ist besser in der Isolationsstufe zu ändern anstatt den NOLOCK-Hinweis verwendet wird). Beachten Sie, dass schmutzig liest, wie der Name eindeutig fest, werden inkonsistente Daten zurückgeben (z. Ihre gesamte Folie kann unausgewogen sein).

Andere Tipps

Dokumentation :

  

Shared (S) Schleusen erlauben gleichzeitige Transaktionen (SELECT) eine Ressource unter pessimistischen Concurrency Control zu lesen. Weitere Informationen finden Sie Types of Concurrency Control. Keine andere Transaktionen können die Daten ändern, während shared (S) Sperren für die Ressource vorhanden ist. Shared (S) Sperren auf einer Ressource werden, sobald der Lesevorgang abgeschlossen ist freigegeben, es sei denn, die Transaktion Isolationsstufe wiederholbar gesetzt lesen oder höher oder ein Verriegelungs Hinweis verwendet wird, um die shared (S) Sperren für die Dauer der Transaktion zu erhalten.

Ein shared lock ist kompatibel mit anderer gemeinsamen Sperre oder einer Update-Sperre, aber nicht mit einer exklusiven Sperre.

Das bedeutet, dass Ihre SELECT Abfragen UPDATE und INSERT Anfragen blockiert und umgekehrt.

Eine SELECT Abfrage wird eine temporäre gemeinsame Sperre setzen, wenn es um einen Block von Werten aus der Tabelle liest, und entfernen Sie es, wenn es zu lesen getan.

Für die Zeit die Sperre existiert, werden Sie nicht in der Lage sein, etwas mit den Daten im gesperrten Bereich zu tun.

Zwei SELECT Abfragen werden nie gegenseitig blockieren

(es sei denn, sie sind SELECT FOR UPDATE)

Sie können SNAPSHOT Isolationsstufe auf Ihrer Datenbank aktivieren und verwenden, aber beachten Sie, dass es UPDATE Abfragen nicht durch SELECT Anfragen aus der Verriegelung verhindern (was Ihren Fall zu sein scheint).

Es wird aber verhindern SELECT Anfragen von durch UPDATE erfasst werden kann.

Beachten Sie auch, dass SQL Server, im Gegensatz zu Oracle, Lock-Manager verwendet und hält sie in einer In-Memory-verkettete Liste sperrt.

Das bedeutet, dass unter hoher Last, die bloße Tatsache des Vergebens und eine Sperre zu entfernen langsam sein kann, da die verkettete Liste sollte sich durch die Transaktion Thread gesperrt werden.

So führen Sie Dirty Reads 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) ..."

nicht vergessen, dass Sie WITH (NOLOCK) schreiben müssen nach jeder Tabelle, die Sie schmutzig lesen möchten

Sie können die Transaktionsebene Uncommitted Lesen

Sie können auch Deadlocks erhalten:

„Deadlocks, die nur eine Tabelle“ http: // sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

und oder falsche Ergebnisse:

"Wählen unter READ COMMITTED und wiederholbaren READ möglicherweise falsche Ergebnisse zurück."

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

Sie können WITH(READPAST) Tabelle Hinweis verwenden. Es ist anders als die WITH(NOLOCK). Es werden die Daten erhalten, bevor die Transaktion gestartet wurde und wird niemanden blockieren. Stellen Sie sich vor, dass Sie die Anweisung lief, bevor die Transaktion gestartet wurde.

SELECT * FROM table1  WITH (READPAST)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top