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

Vermeidung von SQL-Deadlocks durch Abfrageoptimierung:Ratschläge von Brent Ozar

Im Rahmen der Herbstreihe der Database Training Days von Quest präsentierte Brent Ozar, Microsoft Certified Master, ein Tutorial zum Thema „Deadlocks mit Abfrageoptimierung vermeiden“. Das Programm konzentrierte sich auf die drei Parallelitätsprobleme, die in SQL Server auftreten, drei Wege, sie zu beheben, und einen Weg, der sie zu beheben scheint, aber wirklich nicht tut.

Parallelitätsprobleme:Sperren, Blockieren und Deadlocks in SQL Server

Was sind Nebenläufigkeitsprobleme? Sie treten auf, wenn Abfragen versuchen, Konflikte über Datenbankobjekte wie Tabellen zu vermeiden. Sie sind:

  • Sperren – Abfragen tun dies ständig, um zu verhindern, dass andere Abfragen gleichzeitig eine Tabelle verwenden. Dies ist eine normale Datenbankoperation.
  • Blockieren  – Dies tritt auf, wenn eine Abfrage eine normale Sperre hat, aber eine andere Abfrage versucht, dieselbe Sperre zu erwerben. Die zweite Abfrage muss so lange warten, bis die erste Abfrage die Sperre freigibt. Abhängig von der Art der ersten Abfrage kann die zweite sehr kurz oder sehr lange warten. Es sind diese langen Wartezeiten, die sich wirklich auf die Leistung auswirken.
  • Deadlock – Deadlocks treten auf, wenn eine Abfrage eine Sperre übernimmt, eine andere Abfrage eine andere Sperre übernimmt und dann jede die Sperre der anderen abrufen möchte. SQL Server löst dieses Problem, indem es eine der Abfragen als Opfer bestimmt und sie tötet, um die Pattsituation zu überwinden. Auch wenn eine der Abfragen fortgesetzt werden kann, wirkt sich dies ebenfalls auf die Leistung aus.

Behebung von Parallelitätsproblemen

Unabhängig davon, ob Sie Blockaden oder Deadlocks in SQL Server feststellen, gibt es Möglichkeiten, Parallelitätsprobleme zu beheben. Brent stellte diese drei Methoden vor und verbrachte den Großteil der restlichen Sitzung damit, sich auf die zweite zu konzentrieren – die Behebung von fehlerhaftem Code.

  1. Haben Sie genügend Indexe, um Ihre Abfragen schnell zu machen, aber nicht so viele, dass sie die Dinge verlangsamen, indem Abfragen mehr Sperren für längere Zeit halten
  2. Passen Sie Ihren Transaktionscode so an, dass Abfragen Tabellen jedes Mal in der gleichen vorhersehbaren Reihenfolge durchlaufen
  3. Verwenden Sie die richtige Isolationsstufe für die Anforderungen Ihrer Anwendung

Als er in den praktischen Teil des Programms einstieg, kommentierte Brent die Verwendung von NOLOCK-Anweisungen zum Blockieren und Deadlocking. Er warnte davor, dass NOLOCK diese Probleme nicht wirklich behebt, da es auf „Dirty Reads“ beruht – im Wesentlichen ignoriert es die Zeilensperren anderer Abfragen.

In seiner Demonstration mit der Stack Overflow-Datenbank erstellte er eine einfache Abfrage, die nach Personen mit dem Namen „Alex“ suchte und diese zählte. Dann erstellte er eine weitere Abfrage, die ein Update für Personen ausführt, die nicht sind mit dem Namen Alex – keine Einfügungen oder Löschungen von Datensätzen. Eine Abfrage sollte nichts mit der anderen zu tun haben. Wenn sie jedoch zusammen ausgeführt werden, führt dies zu unterschiedlichen Ergebnissen in der Anzahl der Personen mit dem Namen Alex. Dies liegt daran, dass Sie mit NOLOCK Daten sehen können, die nicht festgeschrieben wurden, was zu zufälligen Ergebnissen führt, die Sie nicht vorhersagen können. Es passiert nur unter Parallelität.

Für das Blockieren und Deadlocking in SQL Server ist eindeutig eine bessere Lösung erforderlich, die nicht zu zufälligen und unvorhersehbaren Ergebnissen führt.

Eine bessere Lösung für SQL-Deadlocks

Brent demonstrierte dann, wie man einen Deadlock behebt, indem man den Code ändert, der ihn verursacht. Seine erste Demo zeigte eine einfache Situation mit zwei Tischen, sodass das Publikum einen Stillstand in Zeitlupe sehen konnte, während er passierte. Da SQL Server alle 5 Sekunden nach Deadlocks sucht und die Abfrage beendet, die am einfachsten rückgängig gemacht werden kann, konnten wir sehen, wie das Deadlock-Opfer auftaucht.

In einer einfachen Situation gilt der allgemeinste Rat, nämlich die Tabellen jedes Mal in der gleichen Reihenfolge zu berühren, wenn Sie Abfragen erstellen. Dadurch wird im Allgemeinen verhindert, dass sich Abfragen gegenseitig blockieren.

Was ist mit komplexeren Abfragen? Für dieses Szenario verwendete Brent eine realistischere Situation, die leicht auf Stack Overflow entstehen könnte, wenn zwei Personen die Fragen des anderen positiv bewerten. Da an beiden Transaktionen dieselben Benutzer beteiligt sind, führt dies zu einem Deadlock.

Hier reicht es nicht aus, jeden Tisch jedes Mal in der gleichen Reihenfolge abzuarbeiten, sondern es ist auch notwendig, die Anzahl der Berührungen jedes Tisches zu minimieren. Wie Brent erklärte, kann der Fix hässlichen Code beinhalten, der dazu führt, dass die Abfragen blockiert werden, aber zumindest kein Deadlock. In diesem Fall ist ein kurzer Block, der es ermöglicht, dass beide Abfragen vollständig ausgeführt werden, besser als ein Deadlock, der eine von ihnen beendet.

Niemand möchte den Code in Hunderten von Abfragen ändern, also konzentrieren Sie sich auf diejenigen, die ständig Deadlocks verursachen, entfernen Sie alle unnötigen Zeilen aus der Transaktion und scheuen Sie sich nicht, einen Block einzuführen, um einen Deadlock zu vermeiden.