Comment tuez-vous toutes les connexions actuelles à une base de données SQL Server 2005?

288

Je veux renommer une base de données, mais je reçois toujours l'erreur "Impossible d'obtenir le verrouillage exclusif" sur la base de données, ce qui implique qu'il y a encore une ou plusieurs connexions actives.

Comment puis-je supprimer toutes les connexions à la base de données afin de pouvoir la renommer?

Adam
la source

Réponses:

378

La raison pour laquelle l'approche suggérée par Adam ne fonctionnera pas est que pendant le temps que vous parcourez les connexions actives, une nouvelle peut être établie, et vous les manquerez. Vous pouvez à la place utiliser l'approche suivante qui n'a pas cet inconvénient:

-- set your current connection to use master otherwise you might get an error

use master
ALTER DATABASE YourDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE 

--do you stuff here 

ALTER DATABASE YourDatabase SET MULTI_USER
SQLMenace
la source
1
Cela ne semble pas fonctionner pour SQL Server 2008 ... Voici l'erreur que j'ai obtenue: Console: Msg 102, niveau 15, état 1, ligne 4 Syntaxe incorrecte près de '-'. Msg 319, niveau 15, état 1, ligne 4 Syntaxe incorrecte près du mot clé "avec". Si cette instruction est une expression de table commune, une clause xmlnamespaces ou une clause de contexte de suivi des modifications, l'instruction précédente doit se terminer par un point-virgule. Msg 102, niveau 15, état 1, ligne 4 Syntaxe incorrecte près de «IMMEDIATE». Commande: ALTER DATABASE ASMR-wdanda SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Wagner da Silva
Je viens de l'exécuter en 2008 sans problème ALTER DATABASE aspnetdb SET SINGLE_USER WITH ROLLBACK IMMEDIATE select GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER qu'avez-vous à la place du code commenté?
SQLMenace
A travaillé pour moi avec SQL Server 2008 et l'instance SQL Express.
Tim Murphy
19
@Wagner si la base de données a un '-' dans le nom, vous devez utiliser des crochets autour d'elle: ALTER DATABASE [foo-bar] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Ben Challenor
14
Veuillez noter - N'essayez PAS ceci sur le serveur SQL hébergé sur Amazon RDS. Vous ne pourrez pas réinitialiser la base de données en mode MULTI_USER. Assurez-vous que vous disposez d'un autre ensemble d'informations d'identification DBA avant de tenter cela. J'ai corrigé cela en revenant à l'un des instantanés précédents. Perdu des données. Heureusement, les données n'étaient pas critiques.
RuntimeException
110

Script pour accomplir cela, remplacez 'DB_NAME' par la base de données pour tuer toutes les connexions à:

USE master
GO

SET NOCOUNT ON
DECLARE @DBName varchar(50)
DECLARE @spidstr varchar(8000)
DECLARE @ConnKilled smallint
SET @ConnKilled=0
SET @spidstr = ''

Set @DBName = 'DB_NAME'
IF db_id(@DBName) < 4
BEGIN
PRINT 'Connections to system databases cannot be killed'
RETURN
END
SELECT @spidstr=coalesce(@spidstr,',' )+'kill '+convert(varchar, spid)+ '; '
FROM master..sysprocesses WHERE dbid=db_id(@DBName)

IF LEN(@spidstr) > 0
BEGIN
EXEC(@spidstr)
SELECT @ConnKilled = COUNT(1)
FROM master..sysprocesses WHERE dbid=db_id(@DBName)
END
Adam
la source
1
Cela a fonctionné pour moi, j'ai ajouté and spid <> @@SPIDà la SELECT @sKillConnectiondéclaration afin qu'elle n'essaye pas de tuer ma connexion actuelle, ce qui générerait un message d'erreur.
Luis Perez
Seuls les processus utilisateur peuvent être tués ... toujours bloqués et ne peuvent pas restaurer le mode multi-utilisateurs en raison d'un blocage.
rainabba
mateuscb - la seule façon dont cela ne fonctionnera pas sur mssql 10.00 est si vous avez un nom de base de données qui nécessite [] et que vous ne les utilisez pas. ALTER DATABASE [YourDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE fonctionne en 10, 10.5, 11 et 12.
Jeremy
Gareautrain. Devrait être la meilleure réponse.
gls123
55

Tuez-le et tuez-le avec le feu:

USE master
go

DECLARE @dbname sysname
SET @dbname = 'yourdbname'

DECLARE @spid int
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname)
WHILE @spid IS NOT NULL
BEGIN
EXECUTE ('KILL ' + @spid)
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname) AND spid > @spid
END
btk
la source
27

Utilisation de SQL Management Studio Express:

Dans l'arborescence de l'Explorateur d'objets, descendez sous Gestion jusqu'à "Moniteur d'activité" (si vous ne le trouvez pas, cliquez avec le bouton droit sur le serveur de base de données et sélectionnez "Moniteur d'activité"). En ouvrant le moniteur d'activité, vous pouvez afficher toutes les informations sur le processus. Vous devriez pouvoir trouver les verrous pour la base de données qui vous intéresse et tuer ces verrous, ce qui tuera également la connexion.

Vous devriez pouvoir renommer après cela.

Joseph Daigle
la source
Je ne vois pas cet élément "Moniteur d'activité" sous Gestion ... Encore une fois, c'est peut-être parce que j'utilise SQL 2008?
Wagner da Silva
14
J'ai trouvé un "Activity Montior" si vous faites un clic droit sur le SERVEUR, pas sur la base de données. Vous pouvez ensuite sélectionner l'onglet «Processus» et filtrer par base de données.
alirobe
Vous devez apparemment tuer les processus bloqués un par un, mais c'est une méthode simple qui ne nécessite pas de connexion locale ou de mise hors service du serveur de base de données complet.
Álvaro González
24

J'ai toujours utilisé:


ALTER DATABASE DB_NAME SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
GO 
SP_RENAMEDB 'DB_NAME','DB_NAME_NEW'
Go 
ALTER DATABASE DB_NAME_NEW  SET MULTI_USER -- set back to multi user 
GO 
brendan
la source
21
ALTER DATABASE [Test]
SET OFFLINE WITH ROLLBACK IMMEDIATE

ALTER DATABASE [Test]
SET ONLINE
santhosh kumar
la source
14

Prendre hors ligne prend un certain temps et parfois je rencontre des problèmes avec ça ..

La façon la plus solide à mon avis:

Détacher le clic droit sur la base de données -> Tâches -> Détacher ... cocher "Supprimer les connexions" Ok

Rattacher Cliquez avec le bouton droit sur Bases de données -> Attacher .. Ajouter ... -> sélectionnez votre base de données et modifiez la colonne Attacher en en tant que nom de base de données souhaité. D'accord

NJV
la source
J'aime ça. Le moyen le plus rapide de le faire à partir de l'interface graphique, c'est sûr.
Whelkaholism
Il fonctionne comme un charme! La manière simple est la bonne. Merci.
Tug Strongly
6
Select 'Kill '+ CAST(p.spid AS VARCHAR)KillCommand into #temp
from master.dbo.sysprocesses p (nolock)
join master..sysdatabases d (nolock) on p.dbid = d.dbid
Where d.[name] = 'your db name'

Declare @query nvarchar(max)
--Select * from #temp
Select @query =STUFF((                              
            select '  ' + KillCommand from #temp
            FOR XML PATH('')),1,1,'') 
Execute sp_executesql @query 
Drop table #temp

utilisez la base de données 'master' et exécutez cette requête, cela tuera toutes les connexions actives de votre base de données.

Talha
la source
1
Cela fonctionne vraiment :) Je conseillerais cependant de garder la partie d'exécution de ce script commentée et de mettre une impression @query à la place, juste pour être sûr de ne pas l'exécuter sur un serveur de production par erreur.
Marcello Miorelli
5

Je rencontre généralement cette erreur lorsque j'essaie de restaurer une base de données.Je vais généralement en haut de l'arborescence dans Management Studio et cliquez avec le bouton droit et redémarrez le serveur de base de données (car il se trouve sur une machine de développement, cela pourrait ne pas être idéal en production ). Ceci ferme toutes les connexions à la base de données.

RedWolves
la source
Merci, cela a fonctionné (les ALTER DATABASE ... SET SINGLE_USERcommandes dans les autres réponses ont renvoyé la même erreur «impossible d'obtenir le verrouillage exclusif»).
Tinister
4

Dans MS SQL Server Management Studio sur l'explorateur d'objets, cliquez avec le bouton droit sur la base de données. Dans le menu contextuel qui suit, sélectionnez «Tâches -> Déconnecter»

John Christensen
la source
4
Vous ne pouvez pas faire cela s'il y a une connexion active.
alirobe
4

Une autre approche "tuer avec le feu" consiste à simplement redémarrer le service MSSQLSERVER. J'aime faire des choses depuis la ligne de commande. Le coller exactement dans CMD le fera: NET STOP MSSQLSERVER & NET START MSSQLSERVER

Ou ouvrez "services.msc" et recherchez "SQL Server (MSSQLSERVER)" et faites un clic droit, sélectionnez "redémarrer".

Cela va "à coup sûr, à coup sûr" tuer TOUTES les connexions à TOUTES les bases de données s'exécutant sur cette instance.

(J'aime mieux cela que de nombreuses approches qui changent et changent la configuration sur le serveur / base de données)

aikeru
la source
Que voulez-vous dire «non recommandé»? Si vous n'êtes pas préoccupé par les connexions à ce serveur (par exemple: les environnements de débogage ou de transfert, par exemple - ou un serveur de production avec un temps d'arrêt temporaire), cela peut être le moyen le plus simple. Pour la production - vous ne voulez pas vous occuper de la configuration si vous pouvez simplement redémarrer le service. Qu'est-ce que tu ferais?
aikeru
1
J'irais pour tout ce qui devrait affecter UNIQUEMENT ma base de données cible. votre approche consistant à tuer toutes les bases de données sur le serveur cible n'est pas si intelligente. mais pour être honnête, dans les environnements de mise en scène, c'est peut-être la façon la plus simple, comme vous l'avez dit.
Mohammed Swillam
4

Voici comment faire ce genre de chose de manière fiable dans MS SQL Server Management Studio 2008 (peut également fonctionner pour d'autres versions):

  1. Dans l'arborescence de l'explorateur d'objets, cliquez avec le bouton droit sur le serveur de base de données racine (avec la flèche verte), puis cliquez sur moniteur d'activité.
  2. Ouvrez l'onglet des processus dans le moniteur d'activité, sélectionnez le menu déroulant «bases de données» et filtrez selon la base de données souhaitée.
  3. Cliquez avec le bouton droit sur la base de données dans l'Explorateur d'objets et lancez une tâche «Tâches -> Mettre hors ligne». Laissez cela fonctionner en arrière-plan pendant que vous ...
  4. Arrêtez tout ce que vous pouvez en toute sécurité.
  5. Tuez tous les processus restants à partir de l'onglet processus.
  6. Remettez la DB en ligne.
  7. Renommez la base de données.
  8. Remettez votre service en ligne et pointez-le vers la nouvelle base de données.
alirobe
la source
3

L'option qui fonctionne pour moi dans ce scénario est la suivante:

  1. Démarrez l'opération "Détacher" sur la base de données en question. Cela ouvrira une fenêtre (dans SQL 2005) affichant les connexions actives qui empêchent les actions sur la base de données.
  2. Tuez les connexions actives, annulez l'opération de détachement.
  3. La base de données devrait maintenant être disponible pour la restauration.
Lars Timenes
la source
Dans SQL 2008 Management Studio, pour une raison quelconque, vous ne pouvez plus accéder à la connexion active à partir de l'écran "Détacher". Cela fonctionne très bien en 2005 et c'est comme ça que je l'ai toujours fait, jusqu'à ce que nous passions à 2008 et maintenant tout ce que vous obtenez est un message stupide qui vous dit de fermer votre connexion, mais ne vous laisse pas ouvrir les détails de la connexion pour tuer chaque connexion .
Jim
2

Essaye ça:

ALTER DATABASE [DATABASE_NAME]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
Joseph Sturtevant
la source
2

Cliquez avec le bouton droit sur le nom de la base de données, cliquez sur Propriété pour obtenir la fenêtre des propriétés, ouvrez l'onglet Options et modifiez la propriété "Restreindre l'accès" de Multi-utilisateur à Utilisateur unique. Lorsque vous appuyez sur le bouton OK, il vous invite à fermer toutes les connexions ouvertes, sélectionnez "Oui" et vous êtes prêt à renommer la base de données ....

Sanjay Saxena
la source
2

Ceux-ci ne fonctionnaient pas pour moi (SQL2008 Enterprise), je ne pouvais pas non plus voir de processus en cours ou d'utilisateurs connectés à la base de données. Le redémarrage du serveur (clic droit sur Sql Server dans Management Studio et choisissez Redémarrer) m'a permis de restaurer la base de données.

Le codeur
la source
2

J'utilise SQL Server 2008 R2, ma base de données était déjà définie pour un utilisateur unique et il y avait une connexion qui limitait toute action sur la base de données. Ainsi, la solution recommandée de SQLMenace a répondu par erreur. Voici celui qui a fonctionné dans mon cas .

Ilmar
la source
0

J'utilise sp_who pour obtenir la liste de tous les processus dans la base de données. C'est mieux parce que vous voudrez peut-être revoir le processus à tuer.

declare @proc table(
    SPID bigint,
    Status nvarchar(255),
    Login nvarchar(255),
    HostName nvarchar(255),
    BlkBy nvarchar(255),
    DBName nvarchar(255),
    Command nvarchar(MAX),
    CPUTime bigint,
    DiskIO bigint,
    LastBatch nvarchar(255),
    ProgramName nvarchar(255),
    SPID2 bigint,
    REQUESTID bigint
)

insert into @proc
exec sp_who2

select  *, KillCommand = concat('kill ', SPID, ';')
from    @proc

Résultat
Vous pouvez utiliser la commande dans la colonne KillCommand pour tuer le processus que vous souhaitez.

SPID    KillCommand
26      kill 26;
27      kill 27;
28      kill 28;
Rawitas Krungkaew
la source
-1

Vous pouvez utiliser la commande SP_Who et tuer tous les processus qui utilisent votre base de données, puis renommer votre base de données.

mehdi lotfi
la source