J'ai récemment exécuté une requête de mise à jour sur 100 000 enregistrements. J'ai réalisé que j'avais fait une erreur pendant l'exécution de la requête et j'ai rapidement débranché le câble réseau.
La requête de mise à jour
Comme mentionné par Nick et Martin, le statut éventuel de votre requête dépend de si SQL Server est au courant de votre tirage de câble réseau avant la fin de la requête. De Books Online (bien que je trouve intéressant qu'il y ait des sujets équivalents pour cela dans 20 , 2005 , 2008 , et 2008 R2 , mais pas 2012 ou 2014):
Si une erreur empêche la réussite d'une transaction, SQL Server annule automatiquement la transaction et libère toutes les ressources détenues par la transaction. Si la connexion réseau du client à une instance du moteur de base de données est rompue, toutes les transactions en suspens pour la connexion sont annulées lorsque le réseau notifie l'instance de la rupture. Si l'application cliente échoue ou si l'ordinateur client tombe en panne ou est redémarré, cela interrompt également la connexion et l'instance du moteur de base de données annule toutes les connexions en attente lorsque le réseau l'informe de la rupture. Si le client ferme la session sur l'application, toutes les transactions en suspens sont annulées.
(En passant, les connexions Word dans l'avant-dernière phrase étaient probablement censées être des transactions . Je ne sais pas comment on rétablit une connexion.)
De la même manière, SQL Server peut annuler ou rétablir les transactions pendant la récupération après l'arrêt inattendu du serveur, et cela dépendra de l'état de la transaction au moment de l'arrêt. J'ai vu des gens utiliser cette tactique pour réaliser ce que vous tentiez de faire (annuler la (les) transaction (s)) et lorsque le serveur a redémarré une grande partie du travail a été tout simplement refait (donc l'effet net de leur réaction instinctive était beaucoup plus proche). à zéro que prévu).
Donc, plutôt que d'être soumis à cela, au lieu de faire des choses drastiques dans la panique, comme tirer un câble réseau ou éteindre la machine, je suggère à l'avenir que vous ayez une meilleure discipline pour exécuter des requêtes ad hoc sur des systèmes importants. Par exemple, au lieu de:
UPDATE dbo.sometable
-- where *oops* I forgot this part
Avoir ceci:
BEGIN TRANSACTION;
UPDATE dbo.sometable
-- where *oops* I forgot this part
-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;
Ensuite, si la mise à jour était en effet correcte, vous pouvez mettre en surbrillance la partie COMMIT
et l'exécuter. Si ce n'est pas le cas, vous pouvez calmement mettre en surbrillance la partie ROLLBACK
et l'exécuter. Vous pouvez même utiliser des compléments tels que SSMS Tools Pack pour modifier votre New Query
modèle pour inclure ce passe-partout.
Maintenant, cela pourrait toujours vous poser des problèmes dans le cas où vous exécutez la requête, puis ne faites pas soit valider soit annuler, car maintenant votre transaction bloque d'autres utilisateurs. Mais cela vaut mieux que de modifier irrévocablement les données.
Et bien sûr, comme toujours, disposez d'une sauvegarde sur laquelle vous pouvez compter.
@Aaron a raison. Créer une transaction avant vos commandes est votre meilleur pari. Si vous ne vous souvenez pas de le faire, une option consiste à aller dans le Tools-Options
réglage et activation SET IMPLICIT_TRANSACTIONS
. Cela démarrera automatiquement une transaction dès que certaines commandes seront exécutées. Cela inclut UPDATE
, DELETE
etc. Cela semble être une liste assez complète de toute commande qui "change"
quelque chose. SELECT
est également inclus dans la liste et will
démarre une transaction. Vous pouvez voir une liste complète des commandes qui démarrent une transaction avec ce paramètre ici . Il ne créera pas de transaction si une est déjà démarrée. Maintenant, l'inconvénient est que vous devrez vous rappeler de COMMIT
après toute modification apportée.
REMARQUE: Sur la base de la suggestion de @ Aaron, je vais souligner à nouveau cela.
This is very important! You will have to remember to COMMIT after any change made!
Fondamentalement, vous échangez en oubliant de BEGIN
une transaction et en gâchant quelque chose, pour avoir oublié de COMMIT
une transaction et l'avoir suspendue si vous la laissez ouverte, puis partez pour la journée. J'ai testé juste la fermeture d'une fenêtre de requête en pensant que cela annulerait ma transaction, mais il m'a invité si je voulais valider ou annuler la transaction.
je pense que cela dépend vraiment:
si la commande atteint déjà le serveur avant de débrancher le câble réseau, la commande continuera à s'exécuter normalement.
si vous avez un TransactionScope (utilisé dans .Net, pas sûr d'autres langues) pour encapsuler toutes les commandes de mise à jour, vous ne pouvez probablement arrêter la transaction à être validée que si le transactionScope.Complete () n'a pas été exécuté, mais aucune garantie. .