ALTER DATABASE falhou porque não foi possível colocar um bloqueio no banco de dados

124

Preciso reiniciar um banco de dados porque alguns processos não estão funcionando. Meu plano é colocá-lo offline e novamente online.

Estou tentando fazer isso no Sql Server Management Studio 2008:

use master;
go
alter database qcvalues
set single_user
with rollback immediate;
alter database qcvalues
set multi_user;
go

Estou recebendo estes erros:

Msg 5061, Level 16, State 1, Line 1
ALTER DATABASE failed because a lock could not be placed on database 'qcvalues'. Try again later.
Msg 5069, Level 16, State 1, Line 1
ALTER DATABASE statement failed.
Msg 5061, Level 16, State 1, Line 4
ALTER DATABASE failed because a lock could not be placed on database 'qcvalues'. Try again later.
Msg 5069, Level 16, State 1, Line 4
ALTER DATABASE statement failed.

O que estou fazendo de errado?

JOE SKEET
fonte
Qual é o problema que causou essa necessidade em primeiro lugar? Você tem algumas transações de reversão no momento? Você já executou esse comando em outra janela do SSMS que ainda pode estar aberta? Estou me perguntando (pura especulação) se isso pode levar a um bloqueio que bloqueia outras tentativas, mas ainda está aguardando antes que o banco de dados possa realmente ser colocado no modo de usuário único.
Martin Smith
1
@ Martin - justo o suficiente. Eu devo pensar em outra coisa ou enlouquecer. qualquer um deles é bem possível
codingbadger
@thank a todos muito, eu reiniciado SSMS e foi capaz de matar a todos
JOE SKEET
Pode ser inteligente. Eu apaguei uma consulta incompleta que tinha linhas onduladas tentando acessar o banco de dados e funcionou.
Faahmed

Respostas:

293

Depois de receber o erro, execute

EXEC sp_who2

Procure o banco de dados na lista. É possível que uma conexão não tenha sido encerrada. Se você encontrar alguma conexão com o banco de dados, execute

KILL <SPID>

onde <SPID>é o SPID para as sessões conectadas ao banco de dados.

Experimente o seu script depois que todas as conexões com o banco de dados forem removidas.

Infelizmente, não tenho uma razão para você estar vendo o problema, mas aqui está um link que mostra que o problema ocorreu em outro lugar.

http://www.geakeit.co.uk/2010/12/11/sql-take-offline-fails-alter-database-failed-because-a-locklock-could-not-error-5061/

bobs
fonte
Você pode fornecer alguma explicação sobre por que uma conexão não seria encerrada pelo comando? A única razão pela qual posso pensar seria que ele ainda está em processo de retrocesso ou é uma set single_usertentativa ainda pendente.
Martin Smith
@ Martin, eu tenho medo, não tenho uma razão para isso. Mas adicionarei um link que indica que outras pessoas viram o problema. Concordo que uma reversão de transação pode ser o problema, mas KILLtambém não a resolveria.
bobs
Seja bom em entender por que isso acontece, mas os comentários no seu link parecem indicar que funcionaria! (+1)
Martin Smith
KILL (87) resulta em Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '('.erm ....
Tim Abell
2
@ MartinSmith Acho que sei o porquê: acabei de ter o mesmo problema, uma conexão persistente aparecendo sob sp_who2, causando uma paralisação do desligamento. Acabou sendo uma janela de linhas de edição aberta em ssms. Acredito que o que acontece aqui é que a janela de edição de linhas é uma consulta mantida aberta com um conjunto de resultados editável. O SQL Server possui esse recurso como uma alternativa para atualizar instruções. Ao fechar esta janela de ssms específica, a interrupção do desligamento foi concluída imediatamente.
John
5

Consegui reproduzir esse erro, fazendo o seguinte.

Conexão 1 (deixe em funcionamento por alguns minutos)

CREATE DATABASE TESTING123
GO

USE TESTING123;

SELECT NEWID() AS X INTO FOO
FROM sys.objects s1,sys.objects s2,sys.objects s3,sys.objects s4 ,sys.objects s5 ,sys.objects s6

Conexões 2 e 3

set lock_timeout 5;

ALTER DATABASE TESTING123 SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
Martin Smith
fonte
2

Tente isso se estiver "em transição" ...

http://learnmysql.blogspot.com/2012/05/database-is-in-transition-try-statement.html

USE master
GO

ALTER DATABASE <db_name>

SET OFFLINE WITH ROLLBACK IMMEDIATE
...
...
ALTER DATABASE <db_name> SET ONLINE
Watki02
fonte
Não funciona quando banco de dados está em transição, você vai obter o mesmo erro com a SET OFFLINEdeclaração como mencionado pelo OP (talvez há situações em que trabalha, mas isso não aconteceu para mim)
Abel
1

Vou adicionar isso aqui, caso alguém tenha a mesma sorte que eu.

Ao revisar a lista de processos sp_who2 , observe os processos que são executados não apenas no banco de dados afetado, mas também no mestre . No meu caso, o problema que estava bloqueando o banco de dados estava relacionado a um procedimento armazenado que iniciou um xp_cmdshell.

Verifique se você possui algum processo no estado KILL / RollBack para o banco de dados mestre

SELECT *
FROM sys.sysprocesses
WHERE cmd = 'KILLED/ROLLBACK'

Se você tiver o mesmo problema, apenas o comando KILL provavelmente não ajudará. Você pode reiniciar o servidor SQL ou, melhor, encontrar o cmd.exe nos processos do Windows no sistema operacional SQL Server e matá-lo.

Alina
fonte
0

No SQL Management Studio, vá para Segurança -> Logins e clique duas vezes em seu Logon. Escolha Funções do servidor na coluna esquerda e verifique se sysadmin está marcado.

No meu caso, eu estava logado em uma conta sem esse privilégio.

HTH!

Marty
fonte
1
O erro na pergunta original também acontece quando você é SA, não tem nada a ver com seus direitos. Se você não tiver direitos suficientes, não poderá executar o comando offline.
Abel
0

Matar o ID do processo funcionou muito bem para mim. Ao executar o comando "EXEC sp_who2" em uma nova janela de consulta ... e filtrar os resultados para o banco de dados "ocupado", a execução de processos com o comando "KILL" conseguiu executar o truque. Depois disso tudo funcionou novamente.

user3749524
fonte
0

Só para adicionar meus dois centavos. Eu me coloquei na mesma situação, enquanto pesquisava os privilégios mínimos necessários de um login do db para executar com êxito a instrução:

ALTER DATABASE ... SET SINGLE_USER WITH ROLLBACK IMMEDIATE

Parece que a instrução ALTER é concluída com êxito , quando executada com um login sysadmin , mas requer a parte de limpeza de conexões, quando executada sob um login que possui "apenas" permissões limitadas, como:

ALTER ANY DATABASE

PS: Passei horas tentando descobrir por que o "ALTER DATABASE .." não funciona quando executado sob um logon que possui privilégios de função dbcreator + ALTER ANY DATABASE . Aqui está o meu thread do MSDN !

Veselin Z.
fonte
0

Sei que este é um post antigo, mas recentemente tive um problema muito semelhante. Infelizmente, não pude usar nenhum dos comandos alter database porque um bloqueio exclusivo não pôde ser colocado. Mas nunca consegui encontrar uma conexão aberta com o db. Eventualmente, tive que excluir com força o estado de integridade do banco de dados para forçá-lo a um estado de restauração em vez de em recuperação.

Geoff Dawdy
fonte
0

Em casos raros (por exemplo, depois que uma transação pesada é confirmada), um processo do sistema CHECKPOINT em execução mantendo um bloqueio FILE no arquivo do banco de dados impede a transição para o modo MULTI_USER.

mitix
fonte
0

No meu cenário, não houve processo bloqueando o banco de dados em sp_who2. No entanto, descobrimos, porque o banco de dados é muito maior do que os outros bancos de dados, que os processos pendentes ainda estavam em execução, e é por isso que o banco de dados no grupo de disponibilidade ainda é exibido em vermelho / offline depois de tentarmos 'retomar dados' clicando com o botão direito do mouse no banco de dados em pausa.

Para verificar se você ainda possui processos em execução, basta executar este comando: selecione porcentagem concluída em sys.dm_exec_requests em que percent_complete> 0

user123456789
fonte