it-swarm.com.de

Fehler "Datenbank befindet sich im Übergang"

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 Query Executing..... für einige Zeit und warf dann einen Fehler mit der Aufschrift 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

Zu diesem Zeitpunkt zeigte das SSMS erneut 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. Ich habe versucht, dieselbe Fehlermeldung zurückzugeben. Database is in Transition.

Ich habe auf Google einige Fragen gelesen, bei denen ähnliche Probleme aufgetreten sind, und sie haben empfohlen, das SSMS zu schließen und erneut zu öffnen. Da es sich nur um einen Entwicklungsserver handelt, 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

12
M.Ali

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:

enter image description here

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) und der Versuch, in eine exklusive Sperre (X) zu konvertieren, gewährt. Es hatte einen wait_type von LCK_M_X, blockiert von unserer Sitzung, die durch das erste Abfragefenster (das use <YourDatabase> greift nach einer gemeinsamen Sperre (S) für die Datenbank).

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

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 als "hängen" erscheint, sollten Sie automatisch einen Mangel an Parallelität annehmen und sich mit dem Blockieren befassen (sys.dm_tran_locks ist ein guter Anfang).

Als Randnotiz glaube ich wirklich, dass Sie am besten die Wurzel eines Problems herausfinden, bevor Sie zufällige Maßnahmen ergreifen. Nicht nur bei dieser Operation, sondern bei allen Verhaltensweisen, die Sie nicht erwarten. Wenn Sie wissen, was wirklich Ihr Problem verursacht hat, ist es offensichtlich keine große Sache. Sie hatten im Grunde eine Blockierungskette, und der übergeordnete Blocker war etwas, für das Sie höchstwahrscheinlich gerade ein KILL ausgegeben haben könnten, oder wenn es eine Sitzungsanforderung war, die Sie damals nicht KILL wollten Sie hätten warten können, bis es fertig ist. 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, und es war 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 möchten, wird Ihr ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATE hätte höchstwahrscheinlich ausgereicht, wenn Sie die anfängliche Feststellung getroffen hätten, dass ein Rollback in Ordnung ist.

24
Thomas Stringer

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

4

Sie müssen nichts tun, beenden Sie einfach den Prozess SqLWB.exe Öffnen Sie im Task-Manager 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.

0
garima