web-dev-qa-db-fra.com

Erreur "La base de données est en transition"

Aujourd'hui, j'essayais de restaurer une base de données sur une base de données déjà existante, j'ai simplement fait un clic droit sur la base de données dans SSMS -> Tâches -> Déconnecter pour pouvoir restaurer la base de données.

Une petite fenêtre contextuelle est apparue et a montré Query Executing..... pendant un certain temps, puis a généré une erreur indiquant Database is in use cannot take it offline. À partir de laquelle j'ai recueilli, il existe des connexions actives à cette base de données, j'ai donc essayé d'exécuter la requête suivante

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

Là encore, le SSMS a montré Query Executing..... pendant un certain temps, puis a jeté l'erreur suivante:

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.

Après cela, je n'ai pas pu me connecter à la base de données via SSMS. et quand j'ai essayé de le mettre hors ligne en utilisant SSMS, il a lancé une erreur en disant:

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

À ce stade, je ne pouvais tout simplement pas toucher à la base de données tout ce que j'avais essayé renvoyait le même message d'erreur Database is in Transition.

J'ai lu sur Google des questions où des gens avaient rencontré un problème similaire et ils ont recommandé de fermer le SSMS et de l'ouvrir à nouveau, moi aussi et comme il ne s'agissait que d'un serveur de développement, je viens de supprimer la base de données à l'aide de SSMS et de la restaurer sur une nouvelle base de données.

Ma question est qu'est-ce qui aurait pu causer cela ?? et comment je peux éviter que cela se produise à l'avenir et si jamais je me retrouve dans la même situation à l'avenir, y a-t-il un autre moyen de le réparer autre que de supprimer toute la base de données ???

Je vous remercie

12
M.Ali

Repro

  1. Ouvrez SSMS
  2. Tapez ce qui suit dans une nouvelle fenêtre de requête

    use <YourDatabase>;
    go
    
  3. Passez à Object Explorer (SSMS) et cliquez avec le bouton droit sur <YourDatabase> -> Tasks -> Take Offline
  4. Ouvrez une deuxième nouvelle fenêtre de requête et tapez ce qui suit:

    use <YourDatabase>;
    go
    

Vous serez invité avec le message suivant:

Msg 952, niveau 16, état 1, ligne 1
La base de données 'TestDb1' est en transition. Essayez la déclaration plus tard.

La raison pour laquelle cela se produit peut être trouvée à partir d'une requête de diagnostic similaire à celle ci-dessous:

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;

Pour ce que ça vaut, vous n'avez pas besoin de l'Explorateur d'objets pour reproduire cette erreur. Vous avez juste besoin d'une demande bloquée qui tente la même opération (dans ce cas, mettez la base de données hors ligne). Voir la capture d'écran ci-dessous pour les trois étapes de T-SQL:

enter image description here

Ce que vous verrez très probablement, c'est que votre session Object Explorer est bloquée par une autre session (indiquée par blocking_session_id). Cette session Object Explorer tentera d'obtenir un verrou exclusif (X) sur la base de données. Dans le cas de la repro ci-dessus, la session de l'Explorateur d'objets a obtenu un verrou de mise à jour (U) et a tenté de se convertir en verrou exclusif (X). Il avait un type d'attente de LCK_M_X, bloqué par notre session qui était représentée par la première fenêtre de requête (le use <YourDatabase> saisit un verrou partagé (S) sur la base de données).

Et puis cette erreur est survenue depuis encore une autre session essayant d'obtenir un verrou, et ce message d'erreur se traduit par le refus d'une session pour accéder à une base de données qui tente de passer à une autre état (dans ce cas, état de la transition en ligne vers hors ligne).

Que devez-vous faire la prochaine fois?

Tout d'abord, ne paniquez pas et ne commencez pas à supprimer les bases de données. Vous devez adopter une approche de dépannage (avec une requête de diagnostic similaire à celle ci-dessus) pour savoir pourquoi vous voyez ce que vous voyez. Avec un message comme celui-ci, ou lorsque quelque chose apparaît "bloqué", vous devez automatiquement supposer un manque de simultanéité et commencer à creuser dans le blocage (sys.dm_tran_locks est un bon début).

En passant, je crois vraiment que vous êtes mieux de découvrir la racine d'un problème avant de prendre une mesure aléatoire. Pas seulement avec cette opération, mais cela vaut pour tous les comportements auxquels vous ne vous attendez pas. Sachant ce qui était vraiment à l'origine de votre problème, il est évident que ce n'était vraiment pas grave. Vous aviez essentiellement une chaîne de blocage, et le bloqueur parent était quelque chose sur lequel vous auriez probablement pu émettre un KILL, ou si c'était une demande de session que vous ne vouliez pas KILL alors vous auriez pu attendre sa fin. Quoi qu'il en soit, vous auriez eu les connaissances nécessaires pour prendre la bonne décision et prudente compte tenu de votre scénario particulier (restauration ou attente de validation).

Une autre chose à noter, c'est l'une des raisons pour lesquelles j'ai toujours opté pour l'alternative T-SQL au lieu d'une interface graphique. Vous savez exactement ce que vous exécutez avec T-SQL et ce que fait SQL Server. Après tout, vous avez lancé la commande explicite. Lorsque vous utilisez une interface graphique, le T-SQL réel sera une abstraction. Dans ce cas, j'ai examiné la tentative de l'Explorateur d'objets bloqué de mettre la base de données hors ligne et c'était ALTER DATABASE <YourDatabase> SET OFFLINE. Il n'y a eu aucune tentative de retour en arrière, c'est pourquoi il attendait indéfiniment. Dans votre cas, si vous vouliez restaurer des sessions qui avaient des verrous sur cette base de données, votre ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATE aurait probablement suffi si vous aviez déterminé initialement que la restauration était correcte.

24
Thomas Stringer

La fermeture de SQL Server Management Studio (SSMS) et la réouverture ont résolu le problème pour moi.

4
Michael Bollhoefer

Pas besoin de faire quoi que ce soit, il suffit de tuer le processus SqLWB.exe à partir du Gestionnaire des tâches, ouvrez SQL Server, cliquez avec le bouton droit sur la base de données et mettez-la hors ligne. Si cela ne fonctionne pas, après la fin de la session, tapez la commande

ALTER DATABASE [Test4] SET OFFLINE WITH ROLLBACK IMMEDIATE

puis hors ligne. Cela fonctionnera comme cela a fonctionné pour moi aussi.

0
garima