Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Frage zum SQL-Deadlock

SELECTs können nicht mit anderen SELECTs Deadlocks ausführen, da sie nur gemeinsam genutzte Sperren erwerben. Sie sagen, dass wir berücksichtigen sollten, dass diese SELECTs jetzt 'exklusive Lesesperren erfordern', aber das können wir nicht berücksichtigen, weil 1) es so etwas wie eine exlusive read lock nicht gibt und 2) Lesevorgänge erwerben keine exklusiven Sperren.

Aber Sie stellen eine allgemeinere Frage, ob einfache Aussagen blockieren können. Die Antwort ist ein klares, klares JA . Sperren werden bei der Ausführung erworben, nicht im Voraus analysiert und sortiert und dann in einer bestimmten Reihenfolge erworben. Es wäre für die Engine unmöglich, die erforderlichen Sperren im Voraus zu kennen, da sie von den tatsächlichen Daten auf der Festplatte abhängen, und die Daten zu lesen, die die Engine benötigt, um ... die Daten zu sperren.

Deadlocks zwischen einfachen Anweisungen (SELECT vs. UPDATE oder SELECT vs. DELETE) aufgrund unterschiedlicher Indexzugriffsreihenfolgen sind recht häufig und sehr einfach zu untersuchen, zu diagnostizieren und zu beheben. Aber beachten Sie, dass es immer gibt eine Schreiboperation erforderlich, da Lesevorgänge sich nicht gegenseitig blockieren können. Für diese Diskussion sollte das Hinzufügen eines UPDLOCK- oder XLOCK-Hinweises zu einem SELECT als Schreiben betrachtet werden. Sie brauchen nicht einmal einen JOIN, ein sekundärer Index kann durchaus das Problem der Zugriffsreihenfolge einführen, das zu einem Deadlock führt, siehe Lese-/Schreib-Deadlock .

Und schließlich schreiben Sie SELECT FROM A JOIN B oder schreiben Sie SELECT FROM B JOIN A ist völlig egal. Dem Abfrageoptimierer steht es frei, die Zugriffsreihenfolge nach eigenem Ermessen neu anzuordnen, der eigentliche Text der Abfrage bestimmt in keiner Weise die Ausführungsreihenfolge.

Aktualisiert

Ich fürchte, es gibt kein Cookie-Cutter-Rezept. Die Lösung hängt von Fall zu Fall ab. Letztendlich sind Deadlocks in Datenbankanwendungen eine Tatsache des Lebens. Ich verstehe, dass dies absurd klingen mag, wie in „Wir sind auf dem Mond gelandet, aber wir können keine korrekte Datenbankanwendung schreiben“, aber es spielen starke Faktoren eine Rolle, die ziemlich genau garantieren, dass Anwendungen schließlich auf Deadlocks stoßen. Lucky Deadlocks sind die am einfachsten mit Fehlern umzugehen, einfach den Zustand erneut lesen, die Logik anwenden, den neuen Zustand neu schreiben. Abgesehen davon gibt es einige bewährte Methoden, die die Häufigkeit von Deadlocks drastisch reduzieren können, bis zu dem Punkt, an dem sie so gut wie verschwunden sind:

  • Versuchen Sie, ein konsistentes Zugriffsmuster für Schreibvorgänge zu haben . Haben Sie klar definierte Regeln, die Dinge wie „Eine Transaktion muss immer in dieser Reihenfolge angezeigt werden:Customers -> OrderHeaders -> OrderLines .' Beachten Sie, dass die Bestellung innerhalb einer Transaktion ausgeführt werden muss . Ordnen Sie im Grunde alle Tabellen in Ihrem Schema und geben Sie an, dass alle Aktualisierungen in Rangfolge erfolgen müssen. Dies läuft letztendlich auf die Codedisziplin des einzelnen Mitwirkenden hinaus, der den Code schreibt, da er sicherstellen muss, dass er die Aktualisierung in der richtigen Reihenfolge innerhalb einer Transaktion schreibt.
  • Reduzieren Sie die Dauer von schreibt. Die übliche Weisheit lautet wie folgt:Führen Sie zu Beginn der Transaktion alle Lesevorgänge durch (lesen Sie den vorhandenen Zustand), verarbeiten Sie dann die Logik und berechnen Sie neue Werte und schreiben Sie dann alle Aktualisierungen am Ende der Transaktion. Vermeiden Sie ein Muster wie „Lesen->Schreiben->Logik->Lesen->Schreiben“, sondern „Lesen->Lesen->Logik->Schreiben->Schreiben“. Die wahre Handwerkskunst besteht natürlich darin, mit tatsächlichen, echten Einzelfällen umzugehen, wenn man scheinbar muss muss mitten in der Transaktion schreiben. Eine besondere Anmerkung muss hier zu einem bestimmten Transaktionstyp gemacht werden:jenen, die von einer Warteschlange gesteuert werden, die per Definition ihre Aktivität durch das Herausnehmen (=ein Schreiben) aus der Warteschlange beginnen. Diese Anwendungen waren immer notorisch schwierig zu schreiben und fehleranfällig (insbesondere Deadlocks), zum Glück gibt es Möglichkeiten, dies zu tun, siehe Verwendung von Tabellen als Warteschlangen .
  • Reduzieren Sie die Anzahl der Lesevorgänge. Tabellenscans sind die häufigste Ursache für Deadlocks. Eine ordnungsgemäße Indizierung beseitigt nicht nur Deadlocks, sondern kann auch die Leistung des Prozesses steigern.
  • Snapshot-Isolierung . Dies kommt einem kostenlosen Mittagessen am nächsten, wenn es darum geht, Deadlocks zu vermeiden. Ich habe es absichtlich an letzter Stelle gesetzt, weil es maskieren könnte andere Probleme (z. B. unsachgemäße Indizierung), anstatt sie zu beheben.

Versuchen Sie, dieses Problem mit einem LockCustomerByXXX zu lösen Ansatz funktioniert leider nicht. Pessimistische Sperren skalieren nicht. Optimistische Parallelität Updates sind die Weg zu gehen, wenn Sie irgendeine Art von anständiger Leistung haben wollen.