Beendet das Trennen des Netzwerks eine Abfrage?

13

Ich habe kürzlich eine Aktualisierungsabfrage für 100.000 Datensätze ausgeführt. Mir wurde klar, dass ich während der Abfrage einen Fehler gemacht hatte, und ich zog schnell das Netzwerkkabel heraus.

Führt die Update-Abfrage durch

  1. Verarbeitung beenden und komplett zurücksetzen?
  2. Verarbeitung bis zum Ende fortsetzen und festschreiben?
  3. Verarbeitung beenden und nur einen Teil der Zielzeilen aktualisieren lassen?
robocop
quelle
2
Sobald eine Abfrage den Server erreicht, wird sie fortgesetzt, es sei denn, Sie haben die Abfrage auf dem Server abgebrochen.
JP Chauhan
1
Martins Kommentar liefert die direkte Antwort auf Ihre Frage, Robocop. Wenn das Netzwerk SQL Server über das Trennen der Verbindung benachrichtigt, bevor Ihre Abfrage vollständig ausgeführt wurde, führt SQL Server ein Rollback durch. Andernfalls wird die Abfrage festgeschrieben, wenn sie abgeschlossen ist, bevor SQL Server eine Netzwerkverbindung unterbrochen hat. In keinem Fall (vorausgesetzt, Sie haben eine einzelne Update-Abfrage geschrieben) führt SQL Server ein teilweises Update durch.
Nick Chammas

Antworten:

22

Wie von Nick und Martin erwähnt, hängt der mögliche Status Ihrer Abfrage davon ab, ob SQL Server über Ihren Netzwerkkabelzug informiert ist, bevor die Abfrage abgeschlossen wurde. Aus der Onlinedokumentation (obwohl ich es interessant finde, dass es für 2000 , 2005 , 2008 und 2008 R2 gleichwertige Themen gibt , jedoch nicht für 2012 oder 2014):

Wenn ein Fehler den erfolgreichen Abschluss einer Transaktion verhindert, setzt SQL Server die Transaktion automatisch zurück und gibt alle von der Transaktion gehaltenen Ressourcen frei. Wenn die Netzwerkverbindung des Clients zu einer Instanz des Datenbankmoduls unterbrochen ist, werden alle ausstehenden Transaktionen für die Verbindung zurückgesetzt, wenn das Netzwerk die Instanz über die Unterbrechung benachrichtigt. Wenn die Clientanwendung ausfällt oder der Clientcomputer ausfällt oder neu gestartet wird, wird auch die Verbindung unterbrochen, und die Instanz des Datenbankmoduls setzt alle ausstehenden Verbindungen zurück, wenn das Netzwerk den Ausfall meldet. Wenn der Client die Anwendung abmeldet, werden alle ausstehenden Transaktionen zurückgesetzt.

(Übrigens sollte das Wort Verbindungen im vorletzten Satz wohl sein Transaktion . Ich weiß nicht , wie man rollt eine Verbindung zurück.)

In ähnlicher Weise kann SQL Server während der Wiederherstellung Transaktionen rückgängig machen oder wiederholen, nachdem der Server unerwartet heruntergefahren wurde. Dies hängt vom Status der Transaktion zum Zeitpunkt des Herunterfahrens ab. Ich habe Leute gesehen, die diese Taktik angewendet haben, um das zu erreichen, was Sie versucht haben (die Transaktion (en) abzubrechen), und als der Server wieder hochgefahren wurde, wurde ein Großteil der Arbeit einfach wiederholt (so dass der Nettoeffekt ihrer Knie-Ruck-Reaktion viel enger war auf Null als erwartet).

Ich schlage daher vor, dass Sie in Zukunft mehr Disziplin bei der Ausführung von Ad-hoc-Abfragen für wichtige Systeme haben, als in Panik zu geraten, z. B. ein Netzwerkkabel herauszureißen oder den Computer auszuschalten. Zum Beispiel anstelle von:

UPDATE dbo.sometable 
-- where *oops* I forgot this part

Nimm das:

BEGIN TRANSACTION;

UPDATE dbo.sometable
-- where *oops* I forgot this part

-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;

Wenn das Update korrekt war, können Sie das COMMITTeil markieren und ausführen. Wenn nicht, können Sie das Teil ruhig markieren ROLLBACKund ausführen. Sie können sogar Add-Ins wie SSMS Tools Pack verwenden , um Ihre New QueryVorlage so zu bearbeiten , dass sie diese Boilerplate enthält.

Jetzt kann es immer noch zu Problemen kommen, wenn Sie die Abfrage ausführen und dann nicht entweder Commit oder Rollback, denn jetzt Ihre Transaktion andere Benutzer blockiert. Dies ist jedoch besser, als Daten unwiderruflich zu ändern.

Und natürlich haben Sie wie immer ein Backup, auf das Sie sich verlassen können.

Aaron Bertrand
quelle
5
Dies ist ein ausgezeichneter Rat und behebt die Ursache des OP-Problems, beantwortet jedoch nicht die Frage, ob die Abfrage weiter ausgeführt wird oder nicht.
Nick Chammas
3
Danke @Nick, meine Motivation war es, die Ursache (die die Frage anspornte) anzusprechen, nicht das Symptom, aber ich habe meine Antwort aktualisiert.
Aaron Bertrand
8

@ Aaron ist richtig. Das Erstellen einer Transaktion vor Ihren Befehlen ist die beste Wahl. Wenn Sie sich nicht erinnern können, dass Sie dies getan haben, können Sie in die Tools-OptionsEinstellung gehen und sie einschalten SET IMPLICIT_TRANSACTIONS. Dies startet automatisch eine Transaktion, sobald bestimmte Befehle ausgeführt werden. Dazu gehört UPDATE, DELETEusw. Dies scheint eine ziemlich vollständige Liste aller Befehls zu sein , das wäre "change"etwas. SELECTist ebenfalls in der Liste enthalten und willstartet eine Transaktion. Sie können eine vollständige Liste der Befehle sehen, mit denen eine Transaktion gestartet wird. Diese Einstellung finden Sie hier . Es wird keine Transaktion erstellt, wenn bereits eine gestartet wurde. Nun ist der Nachteil, dass Sie sich daran erinnern müssenCOMMIT nach jeder Änderung .

HINWEIS: Auf der Grundlage des Vorschlags von @ Aaron werde ich dies noch einmal betonen.

This is very important!  You will have to remember to COMMIT after any change made!

Im Grunde handelt es sich dabei um das Vergessen BEGINeiner Transaktion und das Durcheinander, um das Vergessen COMMITeiner Transaktion und das Aufhängen, wenn Sie sie offen lassen und dann für den Tag gehen. Ich habe gerade das Schließen eines Abfragefensters getestet und dachte, es würde meine Transaktion zurücksetzen. Es hat mich jedoch dazu aufgefordert, die Transaktion festzuschreiben oder zurückzusetzen.

Bildbeschreibung hier eingeben

Kenneth Fisher
quelle
Eigentlich: SELECT wird beginnen eine Transaktion (die auch in der Link dokumentiert Sie auf dem Laufenden)
a_horse_with_no_name
Vielen Dank an @a_horse_with_no_name, dass ihr das abgefangen habt! Ich habe nicht genau genug gelesen und eine alte Erinnerung verloren (das war offensichtlich falsch).
Kenneth Fisher
1
Dies ist ein hilfreicher Beitrag, der jedoch nicht die Frage des OP beantwortet, ob die Abfrage weiter ausgeführt wird oder nicht.
Nick Chammas
2
Es war als Ergänzung zu @ Aarons Antwort gedacht. Es war einfach zu viel, um einen Kommentar abzugeben.
Kenneth Fisher
2

Ich denke, es kommt wirklich darauf an:

Wenn der Befehl den Server bereits erreicht, bevor Sie das Netzwerkkabel abgezogen haben, wird der Befehl weiterhin normal ausgeführt.

Wenn Sie über ein TransactionScope (in .Net verwendet, andere Sprachen nicht sicher) verfügen, um alle Aktualisierungsbefehle zu kapseln, können Sie die festgeschriebene Transaktion wahrscheinlich nur stoppen, wenn das transactionScope.Complete () nicht ausgeführt wurde, aber keine Garantie. .

Rex
quelle
2
Sie sagten: "Wenn der Befehl den Server bereits erreicht, bevor Sie das Netzwerkkabel abgezogen haben, wird der Befehl weiterhin normal ausgeführt." Dies wird durch die SQL Server-BOL-Seite widersprochen, auf die Martin oben verlinkt hat. Siehe "Fehler während der Transaktionsverarbeitung" .
Nick Chammas
Du hast recht. Wenn eine Transaktion angegeben ist, wird der Befehl automatisch zurückgesetzt. Als jedoch keine Transaktion explizit angegeben wurde, wurde der Befehl (eine Stapelaktualisierung ohne Transaktion) vollständig ausgeführt, auch wenn wir unsere Anwendung in der Mitte stoppten, wodurch die Verbindung tatsächlich unterbrochen wurde - dies ist jedoch kein besonders gutes Beispiel für das Timing war wohl nicht richtig. wahrscheinlich ist es gut, etwas zu testen
Rex