Frage

Ich habe eine gespeicherte Prozedur, die eine führt von TableB zu TableA verbinden:

 SELECT <--- Nested <--- TableA
             Loop   <--
                      |
                      ---TableB

Zur gleichen Zeit, in einer Transaktion werden Zeilen in TableA eingeführt und dann in TableB.

Diese Situation gelegentlich verursacht Deadlocks, wie die gespeicherte Prozedur packt Reihen wählen Sie aus TableB , während der Einsatz fügt Zeilen TableA , und dann will jeder das andere lassen geht die anderen Tabelle:

INSERT     SELECT
=========  ========
Lock A     Lock B
Insert A   Select B
Want B     Want A
....deadlock...

Logik erfordert die INSERT zur ersten Add Zeilen A und dann auf B , während ich persönlich nicht den Auftrag kümmern, in der SQL Server führt sein beitreten - solange es schließt sich.

Die gemeinsame Empfehlung Deadlocks für die Befestigung ist, dass jeder greift auf Ressourcen in der gleichen Reihenfolge zu gewährleisten. Aber in diesem Fall SQL Server-Optimierer sagen mir, dass das Gegenteil um „besser“ ist. ich kann eine andere Kraft beitreten Ordnung und haben eine schlechtere Durchführung Abfrage.

Aber sollte ich?

Soll ich den Optimierer außer Kraft setzen, jetzt und für immer, mit einem Auftrag kommen, dass ich es verwenden möchten?

oder soll ich nur Trapfehler nativen Fehler 1205 , und erneut die Select-Anweisung?

Die Frage ist nicht, wie viel schlechter ist die Abfrage durchführen könnte, wenn ich die Optimierer außer Kraft setzen und für sie etwas nicht optimal zu tun. Die Frage ist: ist es besser, automatisch Wiederholungs, anstatt schlechte Ausführen von Abfragen

War es hilfreich?

Lösung

Ist es besser, automatisch Wiederholungs Deadlocks. Der Grund dafür ist, dass Sie beheben können das Deadlock, erst später zu einem anderen zu treffen. Das Verhalten zwischen SQL Versionen, wenn die Größe der Tabellen Änderungen ändern, wenn die Server-Hardware-Spezifikationen zu ändern, und selbst wenn die Last auf dem Server ändert. Wenn der Deadlock häufig ist, sollten Sie aktiv Schritte unternehmen, um sie zu beseitigen (ein Index ist in der Regel die Antwort), aber für seltene Deadlocks (sagen alle 10 Minuten oder so), Wiederholungs in der Anwendung kann die Deadlock maskieren. Sie können versuchen Sie es erneut liest oder schreibt, da die Schreibvorgänge sind, natürlich, durch die richtige Transaktion beginnen umgeben / Commit-Transaktion alle Schreiboperationen Atom zu halten und somit in der Lage, sie w / o Probleme erneut zu versuchen.

Ein weiterer Weg zu prüfen, ist das Einschalten engagierten Snapshot . Wenn diese Option aktiviert ist, wird SELECT einfach keine Sperren nehmen, noch ergeben konsistent liest.

Andere Tipps

Deadlocks zu vermeiden, eine der häufigsten Empfehlungen ist es, „acquire Sperren in derselben Reihenfolge“ oder „Zugriff auf Objekte in der gleichen Reihenfolge“. Deutlich macht dies durchaus Sinn, aber es ist immer möglich? Ist es immer möglich? Ich Fälle immer wieder begegnen, wenn ich kann nicht diesen Rat folgen.

Wenn ich ein Objekt in einer übergeordneten Tabelle zu speichern und einem oder mehr Kind Lieben, ich kann nicht diesem Rat überhaupt folgen. Beim Einsetzen, muss ich zuerst meine Eltern Zeile einzufügen. Beim Löschen, ich habe es in der umgekehrten Reihenfolge zu tun.

Wenn ich Befehle verwenden, die mehrere Tabellen oder mehr Zeilen in einer Tabelle berühren, dann in der Regel habe ich keine Kontrolle, in welcher Reihenfolge Sperre erworben werden, (unter der Annahme, dass ich nicht Hinweise verwende).

Also, in vielen Fällen zu acquire Sperren in der gleichen Reihenfolge versuchen, nicht alle Deadlocks verhindern. Wir brauchen also eine Art Deadlocks Handhabung sowieso - wir können nicht davon ausgehen, dass wir sie alle beseitigen. Es sei denn natürlich, serialisiert werden wir alle Zugang mit Service Broker oder sp_getapplock.

Wenn wir nach Deadlocks wiederholen, sind wir sehr wahrscheinlich andere Prozesse Änderungen zu überschreiben. Wir müssen uns bewusst sein, dass es sehr wahrscheinlich jemand anderes die Daten geändert wir ändern soll. Vor allem, wenn alle Leser unter Snapshot-Isolation laufen, dann die Leser nicht in Deadlocks beteiligt sein, was bedeutet, dass alle in einem Deadlock beteiligten Parteien Autoren sind, verändert oder versucht, die gleichen Daten zu ändern. Wenn wir nur die Ausnahme abfangen und automatisch wiederholen, können wir überschreiben jemand andere Änderungen.

Dies ist verloren Updates genannt, und dies ist in der Regel falsch. Typischerweise ist das Richtige nach einem Deadlock zu tun ist, auf einem viel höheren Niveau zu wiederholen -. Die Daten erneut wählen und entscheiden, ob sie in der gleichen Art und Weise zu speichern die ursprüngliche Entscheidung getroffen wurde, speichern

Zum Beispiel, wenn ein Benutzer eine Schaltfläche Speicher und die rettende Transaktion geschoben wurde als Deadlock-Opfer ausgewählt, könnte es eine gute Idee, um Re-Display kann die Daten auf dem Bildschirm, wie der nach dem Stillstand.

Trapping und erneut ausführen kann funktionieren, aber sind Sie sicher, dass die SELECT ist immer das Deadlockopfer? Wenn der Einsatz der Deadlockopfer ist, müssen Sie über Retrying viel vorsichtiger sein.

Die einfachste Lösung in diesem Fall denke ich, ist zu NOLOCK oder READUNCOMMITTED (gleiche) Ihr wählen. Die Menschen haben berechtigte Bedenken über Dirty Reads, aber wir haben für höhere Gleichzeitigkeit seit Jahren NOLOCK ganzen Platz laufen und hatte noch nie ein Problem.

Ich würde auch ein wenig mehr Forschung in Schloss Semantik tun. Zum Beispiel glaube ich weg, wenn Sie Satz Transaktionsisolationsstufe zu Snapshot (erfordert 2005 oder später), um Ihre Probleme zu gehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top