Verwenden von SPID in DB-Tabellen (anstelle von Tabellenvariablen)


8

Transaktionsdatenbank für die Buchung von Dingen ...

Unser Anbieter wurde gebeten, #temptables durch @tablevariables zu ersetzen (aufgrund schwerer Kompilierungssperren). Stattdessen wurde er durch eine tatsächliche Tabelle ersetzt, die SPID als Spalte hinzufügt, um sicherzustellen, dass die gespeicherte Prozedur nur auf die entsprechenden Zeilen wirkt.

Sehen Sie ein Risiko bei dieser Arbeitsweise? Bevor alle Transaktionen innerhalb ihrer eigenen Transaktion isoliert wurden ... Ich befürchtete, dass wir diese Tabelle möglicherweise ein paar Mal sperren, aber sie sind der Meinung, dass SQL Sperren auf Zeilenebene verwendet und dadurch keine weiteren Sperren erstellt werden.

SQL Server-Version: 2016 Enterprise - 13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

1
Es hängt davon ab, ob. Wie viele Sitzungen verwenden gleichzeitig die Tabelle, wie aktiv sind diese Sitzungen, wie viele Datensätze befinden sich in der Tabelle, werden die Datensätze in dieser neuen Tabelle gelöscht oder bleiben sie usw.? 5 Sitzungen, keine große Sache. 500 Sitzungen, die Chancen stehen gut, dass Sie mit temporären Tabellen / Variablen, die für jede Sitzung lokal sind, nicht blockiert werden.
John Eisbrener

Welche Version von SQL Server verwenden Sie?
Anthony Genovese

2016 Enterprise - 13.0.5216.0
Outjet

Datensätze pro Sitzung, die auf die Tabelle treffen, werden 1-50 sein ... sie werden gelöscht, so dass die Tabelle selbst wahrscheinlich nicht mehr als 1.000 Zeilen gleichzeitig erhält ... gleichzeitige Sitzungen wahrscheinlich um die 50 ...
outjet

1
Wenn Sie gezwungen sind, diesen Pfad einzuschlagen (bitte versuchen Sie es zu vermeiden), würde ich ernsthaft darüber nachdenken, den Spid-Wert zu partitionieren und sicherzustellen, dass die Sperreneskalation in der Tabelle auf AUTO gesetzt ist. Dann könnte zumindest das Löschen der Daten eines bestimmten Spids in einem Umschalt- und Abschneidevorgang erfolgen.
Jonathan Fite

Antworten:


5

Ein bisschen mehr Streifzüge, als in einen Kommentarblock passen ... und möchten einen Kommentar hervorheben, den das OP als Antwort auf Rays Antwort abgegeben hat:

  • Der übergeordnete Prozess (Common_InsertOrders_1) erstellt eine temporäre Tabelle
  • Ein untergeordneter Prozess (InsertOrders) fragt die temporäre Tabelle ab
  • Kompilierungssperren werden für den untergeordneten Prozess (InsertOrders) angezeigt.

Für eine Minute auf eine leichte Tangente gehen ... was mit diesem Szenario passieren würde, ist Sybase ASE ...

  • Jede temporäre Tabelle erhält eine eindeutige Objekt-ID (sicher, die Objekt-ID könnte irgendwann wiederverwendet werden, dies ist jedoch selten und wird bei gleichzeitigen Sitzungen sicherlich nicht vorkommen).
  • Sybase ASE erzwingt normalerweise eine Neukompilierung bei jeder Ausführung des untergeordneten Prozesses, da sich die Objekt-ID für die temporäre Tabelle ändert
  • Sybase ASE erzwingt auch eine Neukompilierung des untergeordneten Prozesses, wenn festgestellt wird, dass sich die Struktur der temporären Tabelle zwischen gespeicherten Prozessaufrufen geändert hat (z. B. unterschiedliche Anzahl von Spalten, unterschiedliche Spaltennamen / Datentypen / Nullbarkeit)
  • Neuere Versionen von Sybase ASE verfügen über eine Konfiguration, die den Compiler (effektiv) anweist, Änderungen an temporären Tabellenobjekt-IDs zu ignorieren, wodurch die Neukompilierung des untergeordneten Prozesses vermieden wird (HINWEIS: Neukompilierungen werden weiterhin durchgeführt, wenn sich die Tabellenstruktur ändert).

Zurück zum Problem des OP (Kompilierungssperren für den untergeordneten Prozess) ...

  • Gibt es eine Möglichkeit, dass sich noch einige Spuren des Sybase ASE-Verhaltens in SQL Server befinden (ab dem Zeitpunkt, als die beiden Produkte Erbsen in einem Pod waren)?
  • Gibt es SQL Server-Konfigurationen, die die Neukompilierungen des untergeordneten Prozesses reduzieren (eliminieren?) könnten (wenn dies auf Änderungen der Objekt-ID zurückzuführen ist)?
  • Kann das OP überprüfen, ob der übergeordnete Prozess die temporäre Tabelle jedes Mal mit derselben exakten Struktur / DDL erstellt?

Was die Idee betrifft, eine einzelne permanente Tabelle mit @@ SPID zu verwenden, um Zeilen zwischen Sitzungen zu unterscheiden ... war dort, gesehen, dass ... yuck ; wiederkehrende Probleme:

  • wie / wann verwaiste Zeilen bereinigt werden sollen
  • Die Wiederverwendung der @@ SPID durch das Datenbankmodul kann zu Problemen mit der Datengenauigkeit führen, wenn verwaiste Daten vorhanden sind (oder während der Bereinigung verwaister Daten, z. B. löschen, wenn @@ SPID = 10, aber es gibt eine neue / aktuelle / aktive Sitzung mit @ @ SPID = 10 => die Bereinigung löscht zu viele Daten)
  • Möglichkeit der Eskalation von Sperren von Zeilensperren zu Seiten- / Tabellensperren
  • Wenn die Tabelle Indizes enthält, kann (b) beim Aktualisieren der Indizes gesperrt werden
  • Abhängig davon, in welcher Datenbank sich die Tabelle befindet, können Sie viel mehr Aktivitäten zum Schreiben auf das Protokollgerät in Betracht ziehen (in Sybase ASE ist es möglich, die Protokollierung in tempdb effektiv zu deaktivieren).
  • Selbst (exklusive) Sperren auf Zeilenebene können andere Sitzungen blockieren (abhängig von der Isolationsstufe und davon, ob eine Sitzung diese exklusiven Sperren scannen oder überspringen kann).

Ich möchte zurückgehen und das Grundproblem (Neukompilierungssperren für den untergeordneten Prozess) (erneut) untersuchen und herausfinden, ob es eine Möglichkeit gibt, diese Kompilierungssperren zu reduzieren (zu beseitigen?). [Leider ist mein SQL Server-Wissen zu diesen Themen ... NULL ... und würde mich daher für Eingaben einiger SQL Server-Compiler-Experten interessieren.]


1
Ich stimme zu, ich denke, es muss mehr Zeit für die Untersuchung der Kompilierungssperren aufgewendet werden. Dies hat einige Punkte zu untersuchen. support.microsoft.com/en-us/help/263889/…
Jonathan Fite

8

Es scheint mir, dass die Verwendung von @@SPIDÄhnlichem um Ärger bittet.

Sitzungs-IDs werden häufig wiederverwendet. Sobald sich eine Benutzerverbindung abmeldet, kann diese Sitzungs-ID erneut verwendet werden und wird wahrscheinlich von der nächsten Sitzung verwendet, die versucht, eine Verbindung herzustellen.

Damit es zumindest halbzuverlässig funktioniert, benötigen Sie einen Anmeldetrigger, mit dem vorherige Zeilen aus derselben Tabelle gelöscht werden @@SPID. Wenn Sie dies tun, werden Sie wahrscheinlich feststellen, dass die Tabelle mithilfe der @@SPIDSpalte häufig gesperrt wird.

SQL Server verwendet zwar die Zeilensperre, aber auch die Seiten- und Tabellensperre. Natürlich können Sie dies möglicherweise durch eine gute Indizierung abmildern, aber dies scheint mir immer noch ein Anti-Muster zu sein.

Wenn die gespeicherte Prozedur die einzige Methode ist, die für den Zugriff auf die betroffenen Tabellen verwendet wird, können Sie dies mithilfe einer Anwendungssperre untersuchen, sp_getapplockum den Zugriff auf die relevanten Teile im Wesentlichen zu serialisieren. Docs für sp_getapplock sind hier . Erik Darling hat einen interessanten Beitrag über sie hier .


4

Ja, ich sehe Risiken. Es ist naiv, mit Row Locking auf SQL zu zählen. Ich bin mir zum Beispiel ziemlich sicher, dass beim Einfügen und Löschen zumindest Seitensperren verwendet werden. SQL Engine wählt den Sperrtyp basierend auf mehreren Faktoren aus, und keiner dieser Faktoren enthält "ihre Meinung". Pauschallösungen wie das Ändern von temporären Tabellen in Tabellenvariablen sind im Allgemeinen ebenfalls schlechte Ideen. Tabellenvariablen sind in einigen Situationen sehr nützlich, weisen jedoch Einschränkungen und Leistungsprobleme auf. In den meisten Fällen bevorzuge ich temporäre Tabellen. Besonders wenn die Tabelle mehr als ein paar Dutzend Zeilen enthält. Ich würde vom Anbieter verlangen, zu erklären, warum das System "schwere Kompilierungssperren" aufweist und wie dies die Leistung beeinträchtigt. Denken Sie daran, wann immer Sie hinschauen, werden Sie "schwere Schlösser" finden. Das bedeutet nicht unbedingt, dass die Schlösser ein Problem sind. Max ' s Kommentare zu @@ SPID sind ebenfalls wichtig. Darüber hinaus können das Transaktionsmodell und die Fehlerverarbeitung große Probleme verursachen. Wenn auf Ihrem System Deadlocks oder Probleme mit der Eingabedatenqualität auftreten, kann die Standardfehlerverarbeitung dazu führen, dass die Sitzung beendet wird, ohne dass die Tabelle qryTransactions ordnungsgemäß zurückgesetzt wird. IMO der falsche Lösungsansatz für das ursprüngliche Problem.


Vielen Dank für die Antwort - auf Ihre Punkte: Unsere Traces zeigen, dass LCK stark auf eine Kompilierungssperre für InsertOrders der gespeicherten Prozedur wartet. Es gibt eine übergeordnete Prozedur Common_InsertOrders_1, die die temporäre Tabelle #qryTransactions deklariert, und die verschachtelte Prozedur InsertOrders_2 fragt die temporäre Tabelle ab. Wir haben auch erfahren, dass es auch häufiges Neukompilieren gibt, da nach 6 Änderungen an einer leeren temporären Tabelle jede gespeicherte Prozedur, die auf diese temporäre Tabelle verweist, neu kompiliert werden muss
Outjet

Es gibt viele Gründe, warum eine Prozedur oder Anweisung neu kompiliert wird. MarkP erwähnte einige davon, die in SyBase gelten, und ich bin sicher, dass SQL Server ähnlich ist. Die Anzahl der temporären Tabellenzeilen ist ein gutes Beispiel und die Neukompilierung ist nicht unbedingt eine schlechte Sache. Tabellenstatistiken können den optimalen Abfrageplan erheblich ändern, und eine Neukompilierung ist erforderlich, um dies festzustellen. Aber ich möchte es noch einmal wiederholen. Es wird IMMER eine obere Sperre geben und das bedeutet nicht, dass die Sperre ein Problem ist. Machen Sie sich darüber keine Sorgen, es sei denn, Sie sehen andere Hinweise auf ein Leistungsproblem.
Ray
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.