Deadlock verursacht durch SELECT-JOIN-Anweisung mit SQL-Server

Beim ausführen einer SELECT-Anweisung mit einem JOIN von zwei Tabellen, SQL-Server scheint
sperren Sie beide Tabellen von der Anweisung einzeln. Zum Beispiel, indem Sie eine Abfrage wie
diese:

SELECT ...
FROM
    table1
    LEFT JOIN table2
        ON table1.id = table2.id
    WHERE ...

Fand ich heraus, dass die Reihenfolge der sperren hängt von der WHERE-Bedingung. Die
Abfrageoptimierer versucht, produzieren einen Ausführungsplan, der liest nur so viel
Zeilen wie nötig. Also, wenn die WHERE-Bedingung enthält eine Spalte von Tabelle1
es wird zunächst das Ergebnis Zeilen aus Tabelle1 und dann bekommen Sie die entsprechenden
Zeilen aus Tabelle2. Wenn die Spalte aus Tabelle2 wird es tun das andere Weg
Runde. Komplexere Bedingungen oder die Verwendung von Indizes kann haben einen Effekt an
die Entscheidung des abfrageoptimierers zu.

Wenn die Daten gelesen, indem eine Anweisung aktualisiert werden sollte, später in der Transaktion
mit UPDATE-Anweisungen es ist nicht garantiert, dass die Reihenfolge der AKTUALISIERUNG
Aussagen, die mit der Bestellung übereinstimmt, die verwendet wurde, um Daten zu Lesen und aus den 2 Tabellen.
Wenn eine andere Transaktion versucht, Daten zu Lesen, während eine Transaktion ist die Aktualisierung der
Tabellen es kann einen deadlock verursachen, wenn die SELECT-Anweisung ausgeführt wird
zwischen den UPDATE-Anweisungen, weil weder der WÄHLEN Sie können die Sperre auf
die erste Tabelle noch kann das UPDATE bekommen, die Sperre für die zweite Tabelle. Für
Beispiel:

T1: SELECT ... FROM ... JOIN ...
T1: UPDATE table1 SET ... WHERE id = ?
T2: SELECT ... FROM ... JOIN ... (locks table2, then blocked by lock on table1)
T1: UPDATE table2 SET ... WHERE id = ?

Beide Tabellen stellen eine Typ-Hierarchie und sind immer zusammen verladen. So ist es
Sinn macht das laden eines Objekts mit einem SELECT mit einem JOIN. Beide Tabellen laden
einzeln würde nicht den Abfrageoptimierer eine chance, den besten zu finden
Ausführungsplan. Aber da die UPDATE-Anweisungen können nur aktualisieren einer Tabelle zu einem
Zeit dies kann Ursachen von deadlocks, wenn ein Objekt geladen wird, während das Objekt
aktualisiert wird die von einer anderen Transaktion. Updates von Objekten, die Häufig die Ursache für UPDATEs auf
sowohl Tabellen als Eigenschaften dem Objekt, gehören zu verschiedenen Arten der
Typ-Hierarchie aktualisiert werden.

Ich habe versucht, hinzufügen von sperrhinweisen zu der SELECT-Anweisung, aber das funktioniert nicht
am problem ändern. Es führt genau die Sackgasse, in die SELECT-Anweisungen, wenn
beide Aussagen versuchen zu sperren, die Tabellen und eine SELECT-Anweisung ruft die Sperre
in der entgegengesetzten Reihenfolge der anderen Aussage. Vielleicht wäre es möglich
laden von Daten für die updates immer mit der gleichen Aussage zu zwingen, die sperren zu sein
in der gleichen Reihenfolge. Das würde verhindern, dass ein deadlock zwischen zwei Transaktionen, die
die Daten aktualisieren möchten, aber nicht verhindern, dass eine Transaktion nur liest
Daten zu deadlock, die Bedürfnisse und die unterschiedlichen WHERE-Bedingungen.

Nur Arbeit-a-Runde, so dass diese so weit zu sein scheint, dass liest erhalten möglicherweise nicht sperren
an alle. Mit SQL Server 2005-diese kann getan werden, mithilfe der SNAPSHOT-ISOLATION. Die
einzige Möglichkeit, SQL Server 2000, würde das LESEN UNGEBUNDEN-isolation
Ebene.

Ich würde gerne wissen, ob es eine andere Möglichkeit zu verhindern, dass der SQL-Server
verursacht diese deadlocks?

  • snapshot-isolation-level?
  • Wenn das ist eine Frage, die Antwort ist Nein. Es passiert mit allen Isolationsstufen, vielleicht mit Ausnahme der READ UNCOMMITTED, dass ich nicht testen, weil ich nicht will, dass Transaktionen, die Lesen können, die Hälfte aktualisierten Daten.
InformationsquelleAutor Reboot | 2010-09-14
Schreibe einen Kommentar