J'ai une base de données de développement qui se redéploie fréquemment à partir d'un projet de base de données Visual Studio (via une construction automatique TFS).
Parfois, lorsque j'exécute ma génération, j'obtiens cette erreur:
ALTER DATABASE failed because a lock could not be placed on database 'MyDB'. Try again later.
ALTER DATABASE statement failed.
Cannot drop database "MyDB" because it is currently in use.
J'ai essayé ceci:
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
mais je ne peux toujours pas supprimer la base de données. (Je suppose que la plupart des développeurs ontdbo
accès.)
Je peux exécuter manuellement SP_WHO
et commencer à tuer les connexions, mais j'ai besoin d'un moyen automatique de le faire dans la construction automatique. (Bien que cette fois, ma connexion soit la seule sur la base de données que j'essaie de supprimer.)
Existe-t-il un script qui peut supprimer ma base de données, peu importe qui est connecté?
kill
déclarations tous ensemble. J'utiliserais un curseur pour tuer chaque processus, ce qui bien sûr n'est pas efficace du tout. La technique utilisée dans cette réponse est brillante.USE [Master]
Réf: http://msdn.microsoft.com/en-us/library/bb522682%28v=sql.105%29.aspx
la source
USE master
la clé. J'essayais de supprimer la base de données tout en y étant connecté (Duh!). Merci!SET OFFLINE
vous devez supprimer manuellement les fichiers db.alter database YourDatabaseName set SINGLE_USER with rollback immediate
mieux? Si vous le définissez surOFFLINE
(comme l'indique @mattalxndr), les fichiers seront laissés sur le disque, mais avecSINGLE_USER
votre connexion restera le seul, etdrop database YourDatabaseName
supprimera toujours les fichiers.set offline
, vous pouvez émettreset online
pour éviter le problème des fichiers restants (oui, il existe une possibilité de condition de concurrence).Vous pouvez obtenir le script fourni par SSMS en procédant comme suit:
Le script ressemblera à ceci:
la source
Peu connu: l'instruction GO sql peut prendre un nombre entier pour répéter la commande précédente.
Donc si vous:
Ensuite:
Cela répétera la commande USE 2000 fois, forcera le blocage sur toutes les autres connexions et deviendra propriétaire de la connexion unique. (Donner à votre fenêtre de requête un accès exclusif pour faire ce que vous voulez.)
la source
D'après mon expérience, l'utilisation de SINGLE_USER aide la plupart du temps, cependant, il faut être prudent: j'ai vécu des occasions entre le moment où je lance la commande SINGLE_USER et le moment où elle est terminée ... apparemment, un autre `` utilisateur '' avait obtenu le Accès SINGLE_USER, pas moi. Si cela se produit, vous aurez du mal à récupérer l'accès à la base de données (dans mon cas, c'était un service spécifique en cours d'exécution pour un logiciel avec des bases de données SQL qui avait obtenu l'accès SINGLE_USER avant moi). Ce que je pense devrait être le moyen le plus fiable (je ne peux pas le garantir, mais c'est ce que je vais tester dans les jours à venir), c'est en fait:
- arrêter les services qui peuvent interférer avec votre accès (s'il y en a) - définissez la base de données sur single_user immédiatement après cela - puis effectuez la restauration
- utilisez le script 'kill' ci-dessus pour fermer toutes les connexions
la source
Le script extrêmement efficace de Matthew a été mis à jour pour utiliser le DMV dm_exec_sessions, remplaçant la table système sysprocesses obsolète:
Alternative utilisant la boucle WHILE (si vous souhaitez traiter d'autres opérations par exécution):
la source
La réponse acceptée présente l'inconvénient de ne pas tenir compte du fait qu'une base de données peut être verrouillée par une connexion qui exécute une requête impliquant des tables dans une base de données autre que celle connectée.
Cela peut être le cas si l'instance de serveur a plusieurs bases de données et que la requête directement ou indirectement (par exemple via des synonymes) utilise des tables dans plusieurs bases de données, etc.
Je trouve donc qu'il est parfois préférable d'utiliser syslockinfo pour trouver les connexions à tuer.
Ma suggestion serait donc d'utiliser la variation ci-dessous de la réponse acceptée d'AlexK:
la source
sys.dm_tran_locks
tableau commesyslockinfo
étant obsolète, vous pouvez également exclure votre @@ SPID actuel au cas où.Vous devez faire attention aux exceptions lors des processus de mise à mort. Vous pouvez donc utiliser ce script:
la source
@AlexK a écrit une excellente réponse . Je veux juste ajouter mes deux cents. Le code ci-dessous est entièrement basé sur la réponse de @ AlexK, la différence est que vous pouvez spécifier l'utilisateur et un temps depuis le dernier batch a été exécuté (notez que le code utilise sys.dm_exec_sessions au lieu de master..sysprocess):
Dans cet exemple, seul le processus de l'utilisateur usrDBTest dont le dernier lot a été exécuté il y a plus d'une heure sera tué.
la source
Vous pouvez utiliser le curseur comme ça:
J'ai écrit à ce sujet dans mon blog ici: http://www.pigeonsql.com/single-post/2016/12/13/Kill-all-connections-on-DB-by-Cursor
la source
la source
J'ai testé avec succès avec le code simple ci-dessous
la source
set SINGLE_USER
quand il y avait déjà une seule connexion active.