Como você mata todas as conexões atuais com um banco de dados do SQL Server 2005?


288

Quero renomear um banco de dados, mas continuo recebendo o erro que 'não foi possível obter o bloqueio exclusivo' no banco de dados, o que implica que há algumas conexões ainda ativas.

Como posso matar todas as conexões com o banco de dados para poder renomeá-lo?

Respostas:


378

A razão pela qual a abordagem sugerida por Adam não funcionará é que, durante o tempo em que você estiver percorrendo as conexões ativas, uma nova poderá ser estabelecida, e você sentirá falta dela. Em vez disso, você pode usar a seguinte abordagem, que não tem essa desvantagem:

-- 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

1
Isso não parece funcionar no SQL Server 2008 ... Aqui está o erro que eu tenho: Console: Mensagem 102, Nível 15, Estado 1, Linha 4 Sintaxe incorreta perto de '-'. Msg 319, Nível 15, Estado 1, Linha 4 Sintaxe incorreta perto da palavra-chave 'com'. Se essa instrução for uma expressão de tabela comum, uma cláusula xmlnamespaces ou uma cláusula de contexto de controle de alterações, a instrução anterior deverá ser encerrada com um ponto e vírgula. Msg 102, Nível 15, Estado 1, Linha 4 Sintaxe incorreta perto de 'IMMEDIATE'. Comando: ALTER DATABASE ASMR-wdanda SET SINGLE_USER COM ROLLBACK IMEDIATO
Wagner da Silva

Acabei de executar isso em 2008 sem problemas ALTER DATABASE aspnetdb SET SINGLE_USER WITH ROLLBACK IMMEDIATE selecione GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER O que você tem em vez do código comentado?
SQLMenace 17/08/10

Trabalhou para mim com o SQL Server 2008 e a instância do SQL Express.
Tim Murphy

19
@ Wagner, se o banco de dados tiver um '-' no nome, você precisará usar colchetes: ALTER DATABASE [foo-bar] SET ÚNICO_USER COM ROLLBACK IMEDIATO
Ben Challenor

14
Observação - NÃO tente fazer isso no SQL Server hospedado no Amazon RDS. Você não poderá redefinir o banco de dados novamente para o modo MULTI_USER. Verifique se você tem outro conjunto de credenciais do DBA antes de tentar isso. Corrigi isso revertendo para um dos instantâneos anteriores. Perdeu alguns dados. Felizmente, os dados não foram críticos.
RuntimeException 04/12/14

110

Script para fazer isso, substitua 'DB_NAME' pelo banco de dados para eliminar todas as conexões com:

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

1
Isso funcionou para mim, acrescentei and spid <> @@SPIDà SELECT @sKillConnectiondeclaração para que não tentasse eliminar minha conexão atual, o que geraria uma mensagem de erro.
Luis Perez

Somente processos do usuário podem ser eliminados ... ainda estão em conflito e não podem restaurar o modo multiusuário devido a um conflito.
rainabba

mateuscb- a única maneira de não funcionar no mssql 10.00 é se você tiver um nome de banco de dados que exija [] e não o usar. ALTER DATABASE [yourdatabase] SET SINGLE_USER COM ROLLBACK IMEDIATA trabalha em 10, 10,5, 11 e 12.
Jeremy

Lifesaver. Deve ser a melhor resposta.
precisa

55

Mate-o e mate-o com fogo:

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

27

Usando o SQL Management Studio Express:

Na árvore do Pesquisador de objetos, vá para Gerenciamento em "Monitor de atividades" (se você não conseguir encontrá-lo, clique com o botão direito do mouse no servidor de banco de dados e selecione "Monitor de atividades"). Ao abrir o Activity Monitor, você pode visualizar todas as informações do processo. Você poderá encontrar os bloqueios do banco de dados de seu interesse e eliminar esses bloqueios, o que também matará a conexão.

Você poderá renomear depois disso.


Não vejo esse item "Activity Monitor" em Management ... Novamente, talvez seja porque estou usando o SQL 2008?
Wagner da Silva

14
Encontrei um "Activity Montior" se você clicar com o botão direito do mouse no SERVIDOR, não no DB. Você pode selecionar a guia 'Processos' e filtrar por banco de dados.
alirobe

Aparentemente, você precisa interromper o processo parado, um por um, mas é um método direto que não requer login local ou reduz o servidor de banco de dados completo.
Álvaro González

24

Eu sempre usei:


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 

21
ALTER DATABASE [Test]
SET OFFLINE WITH ROLLBACK IMMEDIATE

ALTER DATABASE [Test]
SET ONLINE

14

Ficar off-line leva um tempo e às vezes tenho alguns problemas com isso.

Maneira mais sólida na minha opinião:

Destacar Clique com o botão direito do mouse em DB -> Tarefas -> Desanexar ... marque "Drop Connections" Ok

Recoloque o botão direito do mouse em Bancos de dados -> Anexar .. Adicionar ... -> selecione seu banco de dados e altere a coluna Anexar como para o nome do banco de dados desejado. Está bem


Gosto disso. A maneira mais rápida de fazer isso a partir da GUI, com certeza.
Whelkaholism

Ele funciona como um encanto! O caminho mais fácil é o melhor. Obrigado.
Tug Fortemente

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

use o banco de dados 'master' e execute esta consulta, ele matará todas as conexões ativas do seu banco de dados.


1
Realmente funciona :) Eu recomendaria, no entanto, manter a parte de execução deste script comentada e colocar uma impressão @query, apenas para ter certeza de que você não executou isso em um servidor de produção por engano.
Marcello Miorelli

5

Normalmente, encontro esse erro quando estou tentando restaurar um banco de dados. Geralmente, apenas vou para o topo da árvore no Management Studio e clico com o botão direito do mouse e reinicio o servidor de banco de dados (porque está em uma máquina de desenvolvimento, isso pode não ser o ideal em produção ) Isso fecha todas as conexões com o banco de dados.


Obrigado, isso funcionou (os ALTER DATABASE ... SET SINGLE_USERcomandos em outras respostas retornaram o mesmo erro 'não foi possível obter o bloqueio exclusivo').
Tinister

4

No MS SQL Server Management Studio, no explorador de objetos, clique com o botão direito do mouse no banco de dados. No menu de contexto a seguir, selecione 'Tarefas -> Desligar'


4
Você não pode fazer isso se houver uma conexão ativa.
alirobe

4

Outra abordagem "mate-o com fogo" é apenas reiniciar o serviço MSSQLSERVER. Eu gosto de fazer coisas na linha de comando. Colar isso exatamente no CMD fará com que: NET STOP MSSQLSERVER & NET START MSSQLSERVER

Ou abra "services.msc" e localize "SQL Server (MSSQLSERVER)" e clique com o botão direito do mouse, selecione "reiniciar".

Isso "com certeza, com certeza" mata TODAS as conexões com TODOS os bancos de dados em execução nessa instância.

(Gosto disso melhor do que muitas abordagens que alteram e alteram a configuração no servidor / banco de dados)


O que você quer dizer com 'não recomendado'? Se você não estiver preocupado com nenhuma conexão com esse servidor (por exemplo: ambientes de depuração ou armazenamento temporário, por exemplo - ou um servidor de produção com tempo de inatividade temporário), essa pode ser a maneira mais fácil. Para produção - você não quer mexer na configuração se puder apenas reiniciar o serviço. O que você faria?
precisa saber é

1
Eu iria para qualquer coisa que deve afetar apenas o meu banco de dados de destino. sua abordagem de matar todos os bancos de dados no servidor de destino não é tão inteligente. mas, para ser sincero, em ambientes de preparação, essa talvez seja a maneira mais fácil como você disse.
Mohammed Swillam

4

Veja como esse tipo de coisa é confiável no MS SQL Server Management Studio 2008 (pode funcionar para outras versões também):

  1. Na Árvore do Pesquisador de Objetos, clique com o botão direito do mouse no servidor de banco de dados raiz (com a seta verde) e clique em monitor de atividades.
  2. Abra a guia processos no monitor de atividades, selecione o menu suspenso 'bancos de dados' e filtre pelo banco de dados que deseja.
  3. Clique com o botão direito do mouse no DB no Pesquisador de Objetos e inicie a tarefa 'Tarefas -> Tirar Offline'. Deixe isso em execução em segundo plano enquanto você ...
  4. Desligue com segurança o que puder.
  5. Mate todos os processos restantes na guia Processo.
  6. Coloque o banco de dados online novamente.
  7. Renomeie o banco de dados.
  8. Coloque seu serviço novamente online e aponte-o para o novo banco de dados.

3

A opção que trabalha para mim nesse cenário é a seguinte:

  1. Inicie a operação "Desanexar" no banco de dados em questão. Isso abrirá uma janela (no SQL 2005) exibindo as conexões ativas que impedem ações no banco de dados.
  2. Mate as conexões ativas, cancele a operação de desanexação.
  3. O banco de dados agora deve estar disponível para restauração.

No SQL 2008 Management Studio, por algum motivo, você não pode mais acessar a conexão ativa na tela "Desanexar". Funciona muito bem em 2005 e é assim que eu sempre fazia, até atualizarmos para 2008 e agora tudo o que você recebe é uma mensagem estúpida que diz para você fechar sua conexão, mas não permite abrir os detalhes da conexão para eliminar cada conexão .
Jim

2

Tente o seguinte:

ALTER DATABASE [DATABASE_NAME]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE

2

Clique com o botão direito do mouse no nome do banco de dados, clique em Propriedades para obter a janela de propriedades, Abra a guia Opções e altere a propriedade "Restringir Acesso" de Multiusuário para Único Usuário. Quando você pressiona o botão OK, ele solicita que você feche todas as conexões abertas, selecione "Sim" e está pronto para renomear o banco de dados ....


2

Eles não funcionaram para mim (SQL2008 Enterprise), também não consegui ver nenhum processo em execução ou usuários conectados ao banco de dados. Reiniciar o servidor (clique com o botão direito do mouse em Sql Server no Management Studio e selecione Reiniciar) me permitiu restaurar o banco de dados.



0

Eu uso sp_who para obter a lista de todos os processos no banco de dados. Isso é melhor porque você pode revisar qual processo matar.

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

Resultado
Você pode usar o comando na coluna KillCommand para matar o processo que deseja.

SPID    KillCommand
26      kill 26;
27      kill 27;
28      kill 28;

-1

Você pode usar o comando SP_Who e eliminar todos os processos que usam seu banco de dados e renomeá-lo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.