it-swarm.com.de

Stoppt das Trennen des Netzwerks eine Abfrage?

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

Führt die Update-Abfrage durch

  1. verarbeitung beenden und vollständig zurücksetzen?
  2. verarbeitung bis zum Abschluss fortsetzen und festschreiben?
  3. verarbeitung beenden und nur einen Teil der Zielzeilen aktualisieren lassen?
13
robocop

Wie von Nick und Martin erwähnt, hängt der endgültige Status Ihrer Abfrage davon ab, ob SQL Server vor Abschluss der Abfrage über Ihren Netzwerkkabelzug Bescheid weiß. Von Books Online (obwohl ich es interessant finde, dass es dafür äquivalente Themen gibt in 20 , 2005 , 2008 und 2008 R2 , aber nicht 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 wird, werden alle ausstehenden Transaktionen für die Verbindung zurückgesetzt, wenn das Netzwerk die Instanz über die Unterbrechung benachrichtigt. Wenn die Clientanwendung fehlschlägt 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 sie über die Unterbrechung benachrichtigt. Wenn der Client die Anwendung abmeldet, werden alle ausstehenden Transaktionen zurückgesetzt.

(Abgesehen davon, dass Word -Verbindungen im vorletzten Satz wahrscheinlich Transaktionen sein sollten . Ich weiß nicht, wie man eine Verbindung zurücksetzt.)

In ähnlicher Weise kann SQL Server Transaktionen während der Wiederherstellung 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 gesehen, dass Leute diese Taktik angewendet haben, um das zu erreichen, was Sie versucht haben (die Transaktion (en) abzubrechen), und als der Server erneut gestartet wurde, wurde ein Großteil der Arbeit einfach wiederholt (sodass der Nettoeffekt ihrer Knie-Ruck-Reaktion viel näher war auf Null als erwartet).

Anstatt dies zu tun, anstatt drastische Dinge in Panik zu tun, wie z. B. ein Netzwerkkabel zu ziehen oder die Maschine auszuschalten, schlage ich vor, dass Sie in Zukunft eine bessere Disziplin bei der Ausführung von Ad-hoc-Abfragen für wichtige Systeme haben. 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 tatsächlich korrekt war, können Sie den Teil COMMIT markieren und ausführen. Wenn nicht, können Sie ruhig den Teil ROLLBACK markieren und ausführen. Sie können sogar Add-Ins wie SSMS Tools Pack verwenden, um Ihre New Query - Vorlage so zu bearbeiten, dass sie diese Boilerplate enthält.

Jetzt könnten Sie immer noch in Schwierigkeiten geraten, wenn Sie die Abfrage ausführen und dann nicht entweder festschreiben oder zurücksetzen, da Ihre Transaktion jetzt 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.

22
Aaron Bertrand

@ Aaron ist richtig. Das Erstellen einer Transaktion vor Ihren Befehlen ist die beste Wahl. Wenn Sie sich nicht daran erinnern können, besteht eine Möglichkeit darin, in das Tools-Options einstellen und einschalten SET IMPLICIT_TRANSACTIONS. Dadurch wird automatisch eine Transaktion gestartet, sobald bestimmte Befehle ausgeführt werden. Dies beinhaltet UPDATE, DELETE usw. Dies scheint eine ziemlich vollständige Liste aller Befehle zu sein, die "change" etwas. SELECT ist ebenfalls in der Liste enthalten und will startet eine Transaktion. Sie können eine vollständige Liste der Befehle sehen, die eine Transaktion starten. Diese Einstellung wird auf hier gesetzt. Es wird keine Transaktion erstellt, wenn bereits eine gestartet wurde. Der Nachteil dabei ist, dass Sie sich nach jeder vorgenommenen Änderung an COMMIT erinnern müssen.

HINWEIS: Auf Vorschlag von @ Aaron werde ich dies noch einmal betonen.

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

Grundsätzlich tauschen Sie es aus, eine Transaktion zu vergessen BEGIN und etwas durcheinander zu bringen, eine Transaktion zu vergessen COMMIT und sie hängen zu lassen, wenn Sie sie offen lassen und dann für den Tag gehen. Ich habe getestet, dass nur ein Abfragefenster geschlossen wurde, weil ich dachte, es würde meine Transaktion zurücksetzen, aber es hat mich dazu aufgefordert, wenn ich die Transaktion festschreiben oder zurücksetzen wollte.

enter image description here

8
Kenneth Fisher

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, nicht sicher in anderen Sprachen) verfügen, um alle Aktualisierungsbefehle zu kapseln, können Sie die Festschreibung der Transaktion wahrscheinlich nur stoppen, wenn die transactionScope.Complete () nicht ausgeführt wurde, jedoch keine Garantie. .

2
Rex