Fehler "Datenbank befindet sich im Übergang"

11

Heute habe ich versucht, eine Datenbank über eine bereits vorhandene Datenbank wiederherzustellen. Ich habe einfach mit der rechten Maustaste auf die Datenbank in SSMS -> Aufgaben -> Offline schalten geklickt, um die Datenbank wiederherzustellen.

Ein kleines Popup-Fenster erschien und zeigte sich Query Executing.....für einige Zeit und warf dann einen Fehler aus Database is in use cannot take it offline. Von denen ich erfahren habe, dass es einige aktive Verbindungen zu dieser Datenbank gibt, habe ich versucht, die folgende Abfrage auszuführen

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

Wieder an diesem Punkt zeigte das SSMS Query Executing.....für eine Weile und warf dann den folgenden Fehler:

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.

Danach konnte ich über SSMS keine Verbindung zur Datenbank herstellen. und als ich versuchte, es mit SSMS offline zu schalten, gab es einen Fehler:

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

Zu diesem Zeitpunkt konnte ich die Datenbank einfach nicht berühren. Alles, was ich versucht habe, gab dieselbe Fehlermeldung zurück Database is in Transition.

Ich habe auf Google einige Fragen gelesen, bei denen Leute mit ähnlichen Problemen konfrontiert waren, und sie haben empfohlen, das SSMS zu schließen und erneut zu öffnen. Da ich nur ein Entwicklungsserver war, habe ich die Datenbank gerade mit SSMS gelöscht und in einer neuen Datenbank wiederhergestellt.

Meine Frage ist, was dies möglicherweise verursacht haben könnte? und wie kann ich vermeiden, dass dies in Zukunft passiert, und wenn ich in Zukunft jemals in der gleichen Situation lande, gibt es eine andere Möglichkeit, dies zu beheben, als die gesamte Datenbank zu löschen?

Vielen Dank

M.Ali
quelle

Antworten:

23

Repro

  1. Öffnen Sie SSMS
  2. Geben Sie Folgendes in ein neues Abfragefenster ein

    use <YourDatabase>;
    go
  3. Gehen Sie zum Objekt-Explorer (SSMS) und klicken Sie mit der rechten Maustaste auf <YourDatabase>-> Tasks->Take Offline
  4. Öffnen Sie ein zweites neues Abfragefenster und geben Sie Folgendes ein:

    use <YourDatabase>;
    go

Sie werden mit der folgenden Meldung aufgefordert:

Nachricht 952, Ebene 16,
Status 1, Zeile 1 Die Datenbank 'TestDb1' befindet sich im Übergang. Versuchen Sie die Aussage später.

Der Grund dafür ist in einer ähnlichen Diagnoseabfrage wie der folgenden zu finden:

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;

Für diesen Zweck benötigen Sie den Objekt-Explorer nicht, um diesen Fehler zu reproduzieren. Sie benötigen lediglich eine blockierte Anforderung, die denselben Vorgang versucht (in diesem Fall schalten Sie die Datenbank offline). Im folgenden Screenshot sind die drei Schritte in T-SQL dargestellt:

Geben Sie hier die Bildbeschreibung ein

Was Sie höchstwahrscheinlich sehen werden, ist, dass Ihre Objekt-Explorer-Sitzung von einer anderen Sitzung blockiert wird (angezeigt durch blocking_session_id). Diese Objekt-Explorer-Sitzung versucht, eine exklusive Sperre ( X) für die Datenbank zu erhalten. Im Fall des obigen Repros wurde der Objekt-Explorer-Sitzung eine Aktualisierungssperre ( U) gewährt und versucht, in eine exklusive Sperre ( X) zu konvertieren . Es hatte einen wait_type von LCK_M_X, der von unserer Sitzung blockiert wurde und durch das erste Abfragefenster dargestellt wurde (das use <YourDatabase>eine gemeinsame Sperre ( S) für die Datenbank abruft ).

Und dann kam dieser Fehler von einer weiteren Sitzung, die versuchte, eine Sperre zu erhalten, und diese Fehlermeldung führte dazu, dass eine Sitzung verweigert wurde, um Zugriff auf eine Datenbank zu erhalten, die versucht, in einen anderen Status überzugehen (in diesem Fall den Online-Status) zum Offline-Übergang).

Was solltest du das nächste Mal tun?

Zunächst einmal keine Panik und keine Datenbanken löschen . Sie müssen eine Fehlerbehebung durchführen (mit einer ähnlichen Diagnoseabfrage wie der oben genannten), um herauszufinden, warum Sie sehen, was Sie sehen. Bei einer solchen Nachricht oder wenn etwas "hängen sys.dm_tran_locksbleibt ", sollten Sie automatisch einen Mangel an Parallelität annehmen und sich mit dem Blockieren befassen (dies ist ein guter Anfang).

Als Randnotiz glaube ich wirklich, dass Sie am besten die Wurzel eines Problems herausfinden sollten, bevor Sie zufällige Maßnahmen ergreifen. Nicht nur bei dieser Operation, sondern bei allen Verhaltensweisen, die Sie nicht erwarten. Wenn Sie wissen, was Ihr Problem wirklich verursacht hat, ist es offensichtlich keine große Sache. Sie hatten im Grunde eine Blockierungskette, und der übergeordnete Blocker war etwas, das Sie höchstwahrscheinlich gerade hätten aktivieren können KILL, oder wenn es sich um eine Sitzungsanforderung handelte, die Sie nicht wollten, hätten KILLSie warten können, bis sie abgeschlossen war. In jedem Fall hätten Sie das Wissen gehabt, die richtige und umsichtige Entscheidung in Ihrem speziellen Szenario zu treffen (Rollback oder Warten auf Commit).

Eine andere erwähnenswerte Sache, dies ist einer der Gründe, warum ich mich immer für die T-SQL-Alternative anstelle einer GUI entscheide. Sie wissen genau, was Sie mit T-SQL ausführen und was SQL Server tut. Immerhin haben Sie den expliziten Befehl ausgegeben. Wenn Sie eine GUI verwenden, wird das eigentliche T-SQL eine Abstraktion sein. In diesem Fall habe ich mir den Versuch des blockierten Objekt-Explorers angesehen, die Datenbank offline zu schalten ALTER DATABASE <YourDatabase> SET OFFLINE. Es gab keinen Versuch, einen Rollback durchzuführen, weshalb auf unbestimmte Zeit gewartet wurde. In Ihrem Fall, wenn Sie Sitzungen mit Sperren für diese Datenbank zurücksetzen wollten, ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATEhätte dies höchstwahrscheinlich ausgereicht, wenn Sie die anfängliche Feststellung getroffen hätten, dass das Zurücksetzen in Ordnung ist.

Thomas Stringer
quelle
1

Durch einfaches Schließen von SQL Server Management Studio (SSMS) und erneutes Öffnen wurde das Problem für mich behoben.

Michael Bollhoefer
quelle
0

Sie müssen nichts tun, beenden Sie den Prozess einfach über den SqLWB.exeTask-Manager, öffnen Sie SQL Server, klicken Sie mit der rechten Maustaste auf die Datenbank und schalten Sie sie offline. Wenn es nicht funktioniert, geben Sie den Befehl ein, nachdem die Sitzung beendet wurde

ALTER DATABASE [Test4] SET OFFLINE WITH ROLLBACK IMMEDIATE

und dann offline. Es wird so funktionieren, wie es auch für mich funktioniert hat.

Garima
quelle