Eu tenho um banco de dados de desenvolvimento que é reimplantado frequentemente de um projeto de banco de dados do Visual Studio (por meio de uma compilação automática do TFS).
Às vezes, quando executo minha compilação, recebo este erro:
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.
Eu tentei isso:
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
mas ainda não consigo descartar o banco de dados. (Meu palpite é que a maioria dos desenvolvedores tem dbo
acesso.)
Posso executar manualmente SP_WHO
e começar a eliminar conexões, mas preciso de uma maneira automática de fazer isso na criação automática. (Embora desta vez minha conexão seja a única no db que estou tentando interromper.)
Existe um script que pode eliminar meu banco de dados, independentemente de quem está conectado?
kill
todas as declarações. Eu usaria um cursor para matar cada processo, o que obviamente não é eficiente. A técnica usada nesta resposta é brilhante.USE [Master]
Ref: http://msdn.microsoft.com/en-us/library/bb522682%28v=sql.105%29.aspx
fonte
USE master
essa a chave. Eu estava tentando soltar o db enquanto conectado a ele (Duh!). Obrigado!SET OFFLINE
precisará excluir manualmente os arquivos db.alter database YourDatabaseName set SINGLE_USER with rollback immediate
seria melhor? Se você defini-loOFFLINE
como (como afirma @mattalxndr), os arquivos serão deixados no disco, mas com aSINGLE_USER
sua conexão, o único será deixado edrop database YourDatabaseName
os arquivos ainda serão removidos.set offline
, você pode emitirset online
para evitar o problema de arquivos restantes (sim, há uma possibilidade de condição de corrida).Você pode obter o script que o SSMS fornece, fazendo o seguinte:
O script será mais ou menos assim:
fonte
Pouco conhecido: a instrução GO sql pode levar um número inteiro pelo número de vezes para repetir o comando anterior.
Então, se você:
Então:
Isso repetirá o comando USE 2000 vezes, forçará o impasse em todas as outras conexões e assumirá a propriedade da conexão única. (Dando acesso exclusivo à sua janela de consulta para fazer o que você desejar).
fonte
Para minha experiência, o uso de SINGLE_USER ajuda na maioria das vezes, no entanto, é preciso ter cuidado: experimentei ocasiões em que entre o momento em que inicio o comando SINGLE_USER e o tempo em que ele é concluído ... aparentemente outro 'usuário' havia obtido o Acesso SINGLE_USER, não eu. Se isso acontecer, você terá um trabalho difícil tentando recuperar o acesso ao banco de dados (no meu caso, era um serviço específico em execução para um software com bancos de dados SQL que conseguiu o acesso SINGLE_USER antes de mim). O que eu acho que deve ser a maneira mais confiável (não posso garantir isso, mas é o que testarei nos próximos dias): na verdade, é:
- interrompa os serviços que podem interferir no seu acesso (se houver)
- use o script 'kill' acima para fechar todas as conexões
- defina o banco de dados como usuário único imediatamente depois disso
- faça a restauração
fonte
O script extremamente eficiente de Matthew atualizado para usar a DMV dm_exec_sessions, substituindo a tabela do sistema sysprocesses descontinuada:
Alternativa usando o loop WHILE (se você quiser processar outras operações por execução):
fonte
A resposta aceita tem o inconveniente de não levar em consideração que um banco de dados pode ser bloqueado por uma conexão que está executando uma consulta que envolve tabelas em um banco de dados diferente daquele conectado.
Pode ser esse o caso se a instância do servidor tiver mais de um banco de dados e a consulta direta ou indiretamente (por exemplo, por meio de sinônimos) usar tabelas em mais de um banco de dados, etc.
Portanto, acho que às vezes é melhor usar o syslockinfo para encontrar as conexões a serem eliminadas.
Minha sugestão seria, portanto, usar a variação abaixo da resposta aceita de AlexK:
fonte
sys.dm_tran_locks
tabela comosyslockinfo
marcada como obsoleta, você também pode excluir o @@ SPID atual apenas por precaução.Você deve ter cuidado com exceções durante os processos de extermínio. Então você pode usar este script:
fonte
@AlexK escreveu uma ótima resposta . Eu só quero adicionar meus dois centavos. O código abaixo é inteiramente baseado na resposta de @ AlexK, a diferença é que você pode especificar o usuário e um tempo desde que o último lote foi executado (observe que o código usa sys.dm_exec_sessions em vez de master..sysprocess):
Neste exemplo, apenas o processo do usuário usrDBTest cujo último lote foi executado há mais de uma hora será eliminado.
fonte
Você pode usar o Cursor assim:
Eu escrevi sobre isso no meu blog aqui: http://www.pigeonsql.com/single-post/2016/12/13/Kill-all-connections-on-DB-by-Cursor
fonte
fonte
Eu testei com sucesso com o código simples abaixo
fonte
set SINGLE_USER
quando já havia uma única conexão ativa.