Erro "O banco de dados está em transição"

12

Hoje eu estava tentando restaurar um banco de dados sobre um banco de dados já existente, simplesmente cliquei com o botão direito do mouse no SSMS -> Tarefas -> Desligar para poder restaurar o banco de dados.

Uma pequena janela pop-up apareceu e apareceu Query Executing.....por algum tempo e, em seguida, gerou um erro dizendo Database is in use cannot take it offline. A partir do qual eu reuni, existem algumas conexões ativas com esse banco de dados, então tentei executar a seguinte consulta

USE master
GO
ALTER DATABASE My_DatabaseName
SET OFFLINE WITH ROLLBACK IMMEDIATE
GO

Novamente, neste momento, o SSMS foi exibido Query Executing.....por algum tempo e, em seguida, lançou o seguinte erro:

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

Depois disso, não consegui me conectar ao banco de dados através do SSMS. e quando tentei colocá-lo offline usando SSMS, ocorreu um erro dizendo:

Database is in Transition. Try later .....

Nesse ponto, eu simplesmente não conseguia tocar no banco de dados, pois qualquer coisa que tentei retornou a mesma mensagem de erro Database is in Transition.

Eu cheguei no google e li algumas perguntas em que as pessoas enfrentavam problemas semelhantes e recomendavam fechar o SSMS e abri-lo novamente. Eu também. Como era apenas um servidor de desenvolvimento, apenas excluí o banco de dados usando o SSMS e restaurado em um novo banco de dados.

Minha pergunta é o que poderia ter causado isso? e como posso evitar que isso aconteça no futuro e se alguma vez eu acabar na mesma situação no futuro, existe alguma outra maneira de corrigi-lo além de excluir o banco de dados inteiro ???

Obrigado

M.Ali
fonte

Respostas:

23

Repro

  1. Abra o SSMS
  2. Digite o seguinte em uma nova janela de consulta

    use <YourDatabase>;
    go
  3. Vá para o Object Explorer (SSMS) e clique com o botão direito do mouse em <YourDatabase>-> Tasks->Take Offline
  4. Abra uma segunda nova janela de consulta e digite o seguinte:

    use <YourDatabase>;
    go

Você será solicitado com a seguinte mensagem:

Msg 952, nível 16, estado 1, linha 1 O
banco de dados 'TestDb1' está em transição. Tente a afirmação mais tarde.

A razão pela qual isso está acontecendo pode ser encontrada em uma consulta de diagnóstico semelhante à abaixo:

select
    l.resource_type,
    l.request_mode,
    l.request_status,
    l.request_session_id,
    r.command,
    r.status,
    r.blocking_session_id,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    request_sql_text = st.text,
    s.program_name,
    most_recent_sql_text = stc.text
from sys.dm_tran_locks l
left join sys.dm_exec_requests r
on l.request_session_id = r.session_id
left join sys.dm_exec_sessions s
on l.request_session_id = s.session_id
left join sys.dm_exec_connections c
on s.session_id = c.session_id
outer apply sys.dm_exec_sql_text(r.sql_handle) st
outer apply sys.dm_exec_sql_text(c.most_recent_sql_handle) stc
where l.resource_database_id = db_id('<YourDatabase>')
order by request_session_id;

Para o que vale a pena, você não precisa do Object Explorer para reproduzir este erro. Você só precisa de uma solicitação bloqueada que está tentando a mesma operação (nesse caso, coloque o banco de dados offline). Veja a captura de tela abaixo para as três etapas no T-SQL:

insira a descrição da imagem aqui

O que você provavelmente verá é a sua sessão do Pesquisador de Objetos sendo bloqueada por outra sessão (mostrada por blocking_session_id). Essa sessão do Object Explorer tentará obter um bloqueio exclusivo ( X) no banco de dados. No caso da reprodução acima, a sessão do Pesquisador de Objetos recebeu um bloqueio de atualização ( U) e tentou converter em um bloqueio exclusivo ( X). Ele tinha um wait_type of LCK_M_X, bloqueado por nossa sessão, representada pela primeira janela de consulta (a use <YourDatabase>captura de um bloqueio compartilhado ( S) no banco de dados).

E, em seguida, esse erro surgiu de mais uma sessão tentando obter um bloqueio, e essa mensagem de erro resulta na negação de uma sessão para obter acesso a um banco de dados que está tentando fazer a transição para um estado diferente (neste caso, o estado online para transição offline).

O que você deve fazer da próxima vez?

Primeiro, não entre em pânico e não comece a soltar bancos de dados . Você precisa adotar uma abordagem de solução de problemas (com uma consulta de diagnóstico semelhante à anterior) para descobrir por que está vendo o que está vendo. Com uma mensagem como essa, ou quando algo parecer "travado", você deve assumir automaticamente uma falta de simultaneidade e começar a procurar o bloqueio ( sys.dm_tran_locksé um bom começo).

Como uma observação lateral, eu realmente acredito que é melhor descobrir a raiz de um problema antes de tomar qualquer ação aleatória. Não apenas com esta operação, mas com todos os comportamentos que você não espera. Sabendo o que realmente estava causando o seu problema, é óbvio que realmente não era grande coisa. Você basicamente tinha uma cadeia de bloqueio, e o bloqueador pai era algo que você provavelmente poderia ter emitido KILL, ou se era uma solicitação de sessão que você não queria, KILLentão poderia ter esperado até que ela fosse concluída. De qualquer forma, você teria o conhecimento necessário para tomar a decisão certa e prudente, considerando seu cenário específico (reversão ou aguardar confirmação).

Outra coisa que vale a pena notar: essa é uma das razões pelas quais eu sempre opto pela alternativa T-SQL em vez de uma GUI. Você sabe exatamente o que está executando com o T-SQL e o que o SQL Server está fazendo. Afinal, você emitiu o comando explícito. Quando você usa uma GUI, o T-SQL real será uma abstração. Nesse caso, observei a tentativa bloqueada do Pesquisador de Objetos de colocar o banco de dados offline e estava ALTER DATABASE <YourDatabase> SET OFFLINE. Não houve tentativa de reversão, e é por isso que estava esperando indefinidamente. No seu caso, se você quisesse reverter as sessões que tinham bloqueios nesse banco de dados, ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATEprovavelmente seria suficiente se tivesse feito a determinação inicial de que a reversão estava correta.

Thomas Stringer
fonte
3

Simplesmente fechar o SQL Server Management Studio (SSMS) e reabrir o problema foi corrigido.

Michael Bollhoefer
fonte
0

Não há necessidade de fazer nada, basta matar o processo SqLWB.exeno Gerenciador de Tarefas, abrir o SQL Server, clicar com o botão direito no banco de dados e colocá-lo offline. Se não funcionar, depois que a sessão for encerrada, digite o comando

ALTER DATABASE [Test4] SET OFFLINE WITH ROLLBACK IMMEDIATE

e depois offline. Funcionará como funcionou para mim também.

garima
fonte