Wie testet man in einer Datenbank auf Rennbedingungen?

30

Ich versuche, Datenbankcode zu schreiben, um sicherzustellen, dass er keinen Rennbedingungen unterliegt, und um sicherzustellen, dass ich die richtigen Zeilen oder Tabellen gesperrt habe. Aber ich frage mich oft: Ist mein Code korrekt? Kann man bestehende Rassenbedingungen zwingen, sich zu manifestieren? Ich möchte sichergehen, dass meine Anwendung das Richtige tut, wenn sie in einer Produktionsumgebung ausgeführt wird.

Ich weiß im Allgemeinen genau, welche gleichzeitige Abfrage wahrscheinlich ein Problem verursacht, aber ich habe keine Ahnung, wie ich sie zwingen kann, gleichzeitig ausgeführt zu werden, um festzustellen, ob das richtige Verhalten vorliegt (z. B. ich habe den richtigen Sperrtyp verwendet), dass die richtigen Fehler vorliegen geworfen, etc.

Hinweis: Ich verwende PostgreSQL und Perl. Wenn dies nicht allgemein beantwortet werden kann, sollte es wahrscheinlich als solches neu gekennzeichnet werden.

Update: Ich würde es vorziehen, wenn die Lösung programmatisch wäre. Auf diese Weise kann ich automatisierte Tests schreiben, um sicherzustellen, dass es keine Regressionen gibt.

Xenoterracid
quelle
Mit "Race Condition" meinen Sie "Deadlock"?
Gaius
2
@Gaius ... nein, obwohl ich glaube, dass dies ein mögliches Ergebnis einiger Rennbedingungen ist
Xenoterracide
Bei @Gaius-Race-Bedingungen in einer Datenbank wird beispielsweise eine Tabelle gelöscht, bevor sie erstellt wurde, oder eine Zeile aktualisiert, bevor sie eingefügt wurde. Generell würde ich mir vorstellen, dass es von der Anwendungslogik außerhalb der Datenbank selbst gehandhabt wird.
Mark D
Eine Zeile vor dem Einfügen aktualisieren? das würde kein db problem verursachen. Eine Race-Bedingung ist nicht das Abrufen und Aktualisieren einer Zeile, sondern das Aktualisieren durch einen anderen Benutzer, nachdem die Zeile abgerufen wurde, aber bevor die Aktualisierung ausgeführt wurde.
Xenoterracide
1
@MarkD - Nein. Es gibt viele Arten von Race-Bedingungen, die sich aus der fehlerhaften Verkapselung einer atomaren Arbeitseinheit in Ihrer Datenbank ergeben. Hier ist ein Beispiel. Denken Sie daran: "Eine Race Condition oder Race Hazard ist ein Fehler in einem elektronischen System oder Prozess, bei dem die Ausgabe oder das Ergebnis des Prozesses unerwartet und kritisch von der Reihenfolge oder dem Zeitpunkt anderer Ereignisse abhängt ." ( Quelle )
Nick Chammas

Antworten:

11

Ich mache das die ganze Zeit mit meinen T-SQL Modulen.

Im Grunde ist alles, was Sie tun müssen, zu tun Ihre Module nur einige Minuten lang über zwei oder mehr Verbindungen in einer Schleife ausführen . In der Regel werden alle potenziellen Probleme in wenigen Minuten angezeigt, vorausgesetzt, Sie haben eine SQL Server-Box mit angemessenen CPUs.

Ich habe hier und hier ein paar Beispiele geschrieben .

AK
quelle
4

Normalerweise arbeite ich mit dem Befehlszeilentool des RDBMS und habe nur 2 (oder mehr) Instanzen der CLI gestartet. Sie können dann eins nach dem anderen und als Rennen wiederholen (das wie ein Action-RPG aussieht) die SQL-Anweisungen, die Ihre Anwendungsebene sendet. Sie sollten die Schließsysteme in Aktion testen / fühlen, da Ihre CLI ein wenig "hängen" bleibt und darauf wartet, dass die Sperren von der anderen CLI freigegeben werden.

Wenn dies klar wie Schlamm klingt, zögern Sie nicht, dies zu sagen ;-)

Julien
quelle
Könnten Sie ein schrittweises Beispiel geben? und können programmatische tests geschrieben werden, um dasselbe zu tun?
Xenoterracide
1

Race Conditions erfordern mehrere Ausführungs-Threads. Um dies zu testen, müssen Sie in der Lage sein, einen oder mehrere Threads zu starten. In Oracle würde ich DBMS_Scheduler verwenden, um einen Prozess zur Simulation eines zweiten Benutzers auszuführen. Wenn PostgreSQL / Perl programmgesteuert einen zweiten Prozess initiieren kann, sollten Sie in der Lage sein, Folgendes zu tun:

Prozess 1 Prozess 2

Starten Sie Prozess 2. >>                            
Verzögerung, damit 2 die Arbeit erledigen können. 
. Zeilen sperren oder Daten ändern.
. Verzögerung, damit 1 seine Arbeit erledigen kann.
Versuchen Sie, Zeilen zu sperren oder Daten zu ändern. .
Überprüfen Sie, ob die ordnungsgemäße Handhabung erfolgt ist. .
Endet. .
                                                Endet.

Es ist gut zu überlegen, wie man mit den Rennbedingungen umgeht und vor allem, wie man sie als Einheit testet.

Leigh Riffel
quelle
Ich würde solche Tests nicht als Unit-Tests bezeichnen, da Unit-Tests jedes Mal genauso ablaufen müssen. Die Rennbedingungen scheitern mitunter an den Prozessen, und dies nicht jedes Mal auf die gleiche Weise.
AK
@AlexKuznetsov Sie haben Recht, dass sich unerwartete Rennbedingungen gelegentlich zeigen können. Das OP bezieht sich jedoch auf erwartete Bedingungen, von denen er glaubt, dass der Code gehandhabt wird. Diese spezifischen Bedingungen können präzise reproduziert und die Handhabung mit einem Komponententest überprüft werden.
Leigh Riffel
-2

Solange Sie Reihen sperren, sollten Sie nicht in einen Rennzustand geraten, wie dies normalerweise der Fall ist, wenn keine Sperre vorhanden ist.

Sie könnten jedoch festgefahren sein, wenn eine Frage Ihre Frage zu lange blockiert.

Dies ist schwer zu testen, da sich die Zeit für Abfragen ändern kann, wenn die Datenbank wächst.

Abfragen, die mit 100 000 Testdatenzeilen einwandfrei funktionieren, werden mit 10 000 000 Zeilen vom Diagramm gestrichen.

Diese Art von Problem kann im Voraus sehr schwierig zu finden sein, aber viele DBs verfügen über eine Methode zum Identifizieren langsamer Abfragen.

Wenn Sie diese Regel verwenden, sollten Sie in der Lage sein, alle Fragen, die in Schwierigkeiten geraten, mit ausreichender Warnung abzufangen.

Wenn Sie alleine sperren, ist es eine andere Geschichte, aber da kann ich nicht helfen.

Nick Chammas
quelle
@darioo lol Ich dachte, vielleicht wäre wn eine Abkürzung für etwas ... idk, was er mit "Selbstsperren" meinen würde. Wenn er nicht mit einem ORM meint, habe ich den Code überprüft, den mein ORM ausgibt, das tut es mit Sicherheit nicht rechts verriegeln. Welches ist einer der Gründe, warum ich in der Lage sein möchte, potenzielle Rennzustands-Szenarien zu testen.
Xenoterracid
Ja, ich meinte "Eigene" und normalerweise handhabt der Datenbanktreiber Sperren, Zeilen, Tabellen oder möglicherweise Felder, aber ich eröffne mich nur für die Möglichkeit, dass Sie eine Datenbank verwenden, die Sperren nicht handhabt;)
.. Ich bin mir ziemlich sicher, dass meine Datenbank bei einer Transaktion mit mehreren Anweisungen nicht weiß, welche Zeilen automatisch gesperrt werden sollen ... Dinge wie select for updatewürden nicht existieren, wenn sie existieren ...
xenoterracide