Jak usunąć bazę danych w trybie pojedynczego użytkownika

12

Jak usunąć bazę danych, która pokazuje się DatabaseName (Single User)jako jej nazwa?

Kiedy próbuję go usunąć, pojawia się następujący błąd:

Zmiana nie powiodła się dla bazy danych „DatabaseName”. (Microsoft.SqlServer.Smo)

Instrukcja ALTER DATABASE nie powiodła się. (Microsoft SQL Server, błąd: 5064)

Próbowałem wykonać ALTERponiżej i nadal mam ten sam problem.

ALTER DATABASE [DatabaseName] SET MULTI_USER WITH NO_WAIT
Prasad Kanaparthi
źródło

Odpowiedzi:

23

Jeśli zamierzasz usunąć bazę danych, musisz być jedynym połączeniem z tą bazą danych. Jeśli istnieją jakieś inne połączenia, nie można go upuścić. Z komunikatu o błędzie (ten błąd oznacza, że ​​twoja baza danych jest w trybie Single_User, ale połączenie już istnieje, więc nie możesz się połączyć), zakładam, że próbowałeś ustawić go w trybie Single_User, a następnie próbowałeś wykonać zrzut, ale albo złapałem połączenie, o którym nie wiedziałeś, lub inny proces. Fakt, że ponowne uruchomienie SSMS działało dla ciebie, mówi mi, że prawdopodobnie złapałeś to połączenie. Oto jak możesz to naprawić.

Logicznie musisz przełączyć bazę danych z powrotem w tryb wielu użytkowników, abyś mógł ponownie wprowadzić ją w tryb pojedynczego użytkownika (ale tym razem będziesz mieć kontrolę nad tym dozwolonym pojedynczym połączeniem i usuniesz bazę danych, zanim coś innego się połączy), a następnie twoja baza danych przepadnij.

W kodzie tutaj jest, jak to zrobić ( ale najpierw zamknij okna zapytań, które są połączone z tą bazą danych. Uruchom ponownie SSMS i upewnij się, że nie wybierasz tej bazy danych w przeglądarce obiektów ):

-- Then attempt to take your database to multi_user mode, do this from master
USE MASTER 
GO

ALTER DATABASE myDatabaseName 
SET multi_user WITH ROLLBACK IMMEDIATE
GO

-- Now put it into single_user mode and drop it. Use Rollback Immediate to disconnect any sessions and rollback their transactions. Safe since you are about to drop the DB.
ALTER DATABASE myDatabaseName
SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

DROP DATABASE myDatabaseName
GO
Mike Walsh
źródło
To rozwiązanie nie będzie działać, jeśli baza danych jest już w trybie pojedynczego użytkownika i spróbujesz uzyskać do niej dostęp z innego połączenia.
Maxim Paukov,
4
Zgadza się Maxim - Dlatego powiedziałem, że moje założenie tutaj oparte na dostarczonych informacjach i samo odpowiedzi PO jest w rzeczywistości tym z otwartym połączeniem, prawdopodobnie za pomocą eksploratora obiektów lub okna zapytania ... Jeśli byłby otwarty w inny sposób innego użytkownika, musisz znaleźć jedno połączenie, które ukradło pojedyncze połączenie, a następnie zabić sesję jednego połączenia i postępować zgodnie z krokami opisanymi powyżej.
Mike Walsh,
13

Jeśli spróbujesz uzyskać dostęp do bazy danych, która jest już w trybie pojedynczego użytkownika, musisz najpierw zamknąć wszystkie połączenia z bazą danych, w przeciwnym razie pojawi się komunikat o błędzie:

Msg 5064, poziom 16, stan 1, wiersz 1 Obecnie nie można dokonać zmian stanu lub opcji bazy danych „Nazwa bazy danych”. Baza danych znajduje się w trybie pojedynczego użytkownika, a użytkownik jest obecnie z nią połączony. Msg 5069, poziom 16, stan 1, wiersz 1 ALTER DATABASE instrukcja nie powiodła się.

Następujące zapytanie zabija procesy dostępu do bazy danych:

-- Create the sql to kill the active database connections  
declare @execSql varchar(1000), @databaseName varchar(100)  
-- Set the database name for which to kill the connections  
set @databaseName = 'DatabaseName'  

set @execSql = ''   
select  @execSql = @execSql + 'kill ' + convert(char(10), spid) + ' '  
from    master.dbo.sysprocesses  
where   db_name(dbid) = @databaseName  
     and  
     DBID <> 0  
     and  
     spid <> @@spid  
exec(@execSql)
GO

Następnie powinieneś być w stanie przywrócić bazę danych z powrotem do trybu wielu użytkowników:

ALTER DATABASE 'DatabaseName' SET MULTI_USER
Maxim Paukov
źródło
2
Jest to bardzo, bardzo kłopotliwe rozwiązanie i odpowiada frustrującej grze walenia w molo w ruchliwym systemie. Aby wyrzucić wszystkich użytkowników, jest o wiele łatwiejszy w użyciu, ALTER DATABASE SET SINGLE_USER WITH ROLLBACK IMMEDIATEjak pokazuje odpowiedź Mike'a.
Aaron Bertrand
1
@AaronBertrand Rozwiązanie Mike'a nie będzie działać, jeśli baza danych jest już w trybie pojedynczego użytkownika i spróbujesz uzyskać do niej dostęp z innego połączenia.
Maxim Paukov,
2
Racja, jeśli tak jest, musiałby znaleźć sesje zgodnie z twoimi wskazówkami. Jeśli jednak połączenie, które ustawiło bazę danych na single_user, jest jego własne ...
Aaron Bertrand