Jak zabić wszystkie bieżące połączenia z bazą danych SQL Server 2005?

288

Chcę zmienić nazwę bazy danych, ale wciąż pojawia się błąd, że „nie można uzyskać wyłącznej blokady” w bazie danych, co oznacza, że ​​niektóre połączenia są nadal aktywne.

Jak mogę zabić wszystkie połączenia z bazą danych, aby móc zmienić jej nazwę?

Adam
źródło

Odpowiedzi:

378

Powodem, dla którego Adam zasugerował, że nie zadziała, jest to, że w czasie, gdy zapętlasz aktywne połączenia, można ustanowić nowe, a ty ich przegapisz. Zamiast tego możesz zastosować następujące podejście, które nie ma tej wady:

-- set your current connection to use master otherwise you might get an error

use master
ALTER DATABASE YourDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE 

--do you stuff here 

ALTER DATABASE YourDatabase SET MULTI_USER
SQLMenace
źródło
1
Wydaje się, że to nie działa w przypadku SQL Server 2008 ... Oto błąd, który dostałem: Konsola: Msg 102, poziom 15, stan 1, wiersz 4 Niepoprawna składnia w pobliżu '-'. Msg 319, poziom 15, stan 1, wiersz 4 Niepoprawna składnia w pobliżu słowa kluczowego „z”. Jeśli ta instrukcja jest wspólnym wyrażeniem tabelowym, klauzulą ​​xmlnamespaces lub klauzulą ​​kontekstu śledzenia zmian, poprzednia instrukcja musi być zakończona średnikiem. Msg 102, poziom 15, stan 1, wiersz 4 Niepoprawna składnia w pobliżu „NATYCHMIAST”. Polecenie: ZMIEŃ bazę danych ASMR-wdanda ZESTAW POJEDYNCZY_UŻYTKOWNIKA Z ROLLBACK NATYCHMIAST
Wagner da Silva
Właśnie uruchomiłem to w 2008 roku bez problemów ALTER DATABASE aspnetdb SET SINGLE_USER WITH ROLLBACK NATYCHMIAST wybierz GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER co masz zamiast skomentowanego kodu?
SQLMenace
Pracowałem dla mnie z wystąpieniem SQL Server 2008 i SQL Express.
Tim Murphy,
19
@ Wagner, jeśli baza danych ma w nazwie znak „-”, należy użyć nawiasów: ALTER DATABASE [foo-bar] SET SINGLE_USER WITH ROLLBACK NATYCHMIAST
Ben Challenor
14
Uwaga - NIE próbuj tego na SQL Server hostowanym na Amazon RDS. Nie będzie można zresetować DB z powrotem do trybu MULTI_USER. Przed podjęciem próby upewnij się, że masz inny zestaw poświadczeń DBA. Naprawiłem to, przywracając jedną z poprzednich migawek. Straciłem trochę danych. Na szczęście dane nie były krytyczne.
RuntimeException
110

Skrypt, aby to zrobić, zamień „DB_NAME” na bazę danych, aby zabić wszystkie połączenia z:

USE master
GO

SET NOCOUNT ON
DECLARE @DBName varchar(50)
DECLARE @spidstr varchar(8000)
DECLARE @ConnKilled smallint
SET @ConnKilled=0
SET @spidstr = ''

Set @DBName = 'DB_NAME'
IF db_id(@DBName) < 4
BEGIN
PRINT 'Connections to system databases cannot be killed'
RETURN
END
SELECT @spidstr=coalesce(@spidstr,',' )+'kill '+convert(varchar, spid)+ '; '
FROM master..sysprocesses WHERE dbid=db_id(@DBName)

IF LEN(@spidstr) > 0
BEGIN
EXEC(@spidstr)
SELECT @ConnKilled = COUNT(1)
FROM master..sysprocesses WHERE dbid=db_id(@DBName)
END
Adam
źródło
1
Działa to dla mnie, dodałem and spid <> @@SPIDdo SELECT @sKillConnectioninstrukcji, aby nie próbowała zabić mojego obecnego połączenia, co spowodowałoby wygenerowanie komunikatu o błędzie.
Luis Perez
Tylko procesy użytkownika mogą zostać zabite ... wciąż zablokowane i nie mogą przywrócić trybu wielu użytkowników z powodu zakleszczenia.
rainabba,
mateuscb - jedynym sposobem, aby nie działał na mssql 10.00 jest, jeśli masz nazwę bazy danych, która wymaga [] i nie używasz ich. Alter database [YourDatabase] ustawioną SINGLE_USER Wycofywanie BEZPOŚREDNIE działa 10, 10,5, 11 i 12
Jeremy
Ratownik. Powinna być najlepsza odpowiedź.
gls123
55

Zabij go i zabij ogniem:

USE master
go

DECLARE @dbname sysname
SET @dbname = 'yourdbname'

DECLARE @spid int
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname)
WHILE @spid IS NOT NULL
BEGIN
EXECUTE ('KILL ' + @spid)
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname) AND spid > @spid
END
btk
źródło
27

Za pomocą SQL Management Studio Express:

W drzewie Eksploratora obiektów przejdź do sekcji Zarządzanie do „Monitor aktywności” (jeśli nie możesz go tam znaleźć, kliknij prawym przyciskiem myszy serwer bazy danych i wybierz „Monitor aktywności”). Otwierając Monitor aktywności, możesz wyświetlić wszystkie informacje o procesie. Powinieneś być w stanie znaleźć blokady dla bazy danych, którą jesteś zainteresowany, i zabić te blokady, które również zabiją połączenie.

Po tym powinieneś być w stanie zmienić nazwę.

Joseph Daigle
źródło
Nie widzę tego elementu „Monitor aktywności” w obszarze Zarządzanie ... Może znowu dlatego, że używam SQL 2008?
Wagner da Silva
14
Znalazłem „Aktywność Montiora”, jeśli klikniesz prawym przyciskiem myszy SERWER, a nie DB. Następnie możesz wybrać kartę „Procesy” i filtrować według bazy danych.
alirobe,
Najwyraźniej musisz zabijać zablokowany proces jeden po drugim, ale jest to prosta metoda, która nie wymaga lokalnego logowania ani wyłączania całego serwera bazy danych.
Álvaro González
24

Zawsze używałem:


ALTER DATABASE DB_NAME SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
GO 
SP_RENAMEDB 'DB_NAME','DB_NAME_NEW'
Go 
ALTER DATABASE DB_NAME_NEW  SET MULTI_USER -- set back to multi user 
GO 
brendan
źródło
21
ALTER DATABASE [Test]
SET OFFLINE WITH ROLLBACK IMMEDIATE

ALTER DATABASE [Test]
SET ONLINE
Santhosh Kumar
źródło
14

Odłączenie się zajmuje trochę czasu, a czasem mam z tym pewne problemy ...

Najbardziej solidny sposób moim zdaniem:

Odłącz Kliknij prawym przyciskiem myszy DB -> Zadania -> Odłącz ... zaznacz „Zrzuć połączenia” Ok

Ponownie podłącz Kliknij prawym przyciskiem myszy Bazy danych -> Załącz .. Dodaj ... -> wybierz bazę danych i zmień kolumnę Dołącz jako na żądaną nazwę bazy danych. Dobrze

NJV
źródło
Lubię to. Na pewno najszybszy sposób na zrobienie tego z GUI.
Whelkaholism
To działa jak urok! Łatwy sposób to dobry sposób. Dzięki.
Tug Strongly
6
Select 'Kill '+ CAST(p.spid AS VARCHAR)KillCommand into #temp
from master.dbo.sysprocesses p (nolock)
join master..sysdatabases d (nolock) on p.dbid = d.dbid
Where d.[name] = 'your db name'

Declare @query nvarchar(max)
--Select * from #temp
Select @query =STUFF((                              
            select '  ' + KillCommand from #temp
            FOR XML PATH('')),1,1,'') 
Execute sp_executesql @query 
Drop table #temp

użyj „głównej” bazy danych i uruchom tę kwerendę, zabije ona wszystkie aktywne połączenia z bazy danych.

Talha
źródło
1
To naprawdę działa :) Radziłbym jednak, aby zachować komentarz do wykonania części tego skryptu i zamiast tego wstawić print @query, aby mieć pewność, że nie uruchomisz go przypadkowo na serwerze produkcyjnym.
Marcello Miorelli,
5

Zwykle napotykam ten błąd, gdy próbuję przywrócić bazę danych. Zwykle po prostu wchodzę na szczyt drzewa w Management Studio i klikam prawym przyciskiem myszy i ponownie uruchamiam serwer bazy danych (ponieważ znajduje się na komputerze programistycznym, może nie być idealny w środowisku produkcyjnym ). To zamyka wszystkie połączenia z bazą danych.

RedWolves
źródło
Dzięki, zadziałało ( ALTER DATABASE ... SET SINGLE_USERpolecenia w innych odpowiedziach zwróciły ten sam błąd „nie można uzyskać blokady wyłącznej”).
Tinister
4

W MS SQL Server Management Studio w eksploratorze obiektów kliknij bazę danych prawym przyciskiem myszy. W menu kontekstowym, które następuje, wybierz „Zadania -> Przełącz offline”

John Christensen
źródło
4
Nie możesz tego zrobić, jeśli istnieje aktywne połączenie.
alirobe,
4

Innym podejściem „zabić go ogniem” jest ponowne uruchomienie usługi MSSQLSERVER. Lubię robić rzeczy z wiersza poleceń. Wklei to dokładnie do CMD to zrobi: NET STOP MSSQLSERVER i NET START MSSQLSERVER

Lub otwórz „services.msc” i znajdź „SQL Server (MSSQLSERVER)” i kliknij prawym przyciskiem myszy, wybierz „uruchom ponownie”.

To „na pewno na pewno” zabije WSZYSTKIE połączenia z WSZYSTKIMI bazami danych uruchomionymi w tej instancji.

(Podoba mi się to bardziej niż wiele podejść, które zmieniają i przywracają konfigurację na serwerze / bazie danych)

aikeru
źródło
Co masz na myśli mówiąc „niezalecane”? Jeśli nie obawiasz się żadnych połączeń z tym serwerem (np. Środowiskami debugowania lub przemieszczania - lub serwerem produkcyjnym z tymczasowym czasem przestoju), może to być najłatwiejszy sposób. Do produkcji - nie chcesz tracić czasu na konfigurację, jeśli możesz po prostu zrestartować usługę. Co byś zrobił?
aikeru
1
Wybrałbym wszystko, co powinno wpłynąć TYLKO na moją docelową bazę danych. twoje podejście do zabijania wszystkich baz danych na serwerze docelowym nie jest takie mądre. ale szczerze mówiąc, w środowiskach inscenizacyjnych może to być najłatwiejszy sposób, jak powiedziałeś.
Mohammed Swillam
4

Oto jak niezawodnie tego rodzaju rzeczy w MS SQL Server Management Studio 2008 (może działać również w przypadku innych wersji):

  1. W drzewie eksploratora obiektów kliknij prawym przyciskiem myszy główny serwer bazy danych (zieloną strzałką), a następnie kliknij monitor aktywności.
  2. Otwórz kartę procesów w monitorze aktywności, wybierz menu rozwijane „bazy danych” i filtruj według żądanej bazy danych.
  3. Kliknij prawym przyciskiem myszy bazę danych w Eksploratorze obiektów i uruchom zadanie „Zadania -> Przełącz offline”. Pozostaw to uruchomione w tle, podczas gdy ...
  4. Bezpiecznie wyłącz wszystko, co możesz.
  5. Zabij wszystkie pozostałe procesy z zakładki procesu.
  6. Ponownie włącz DB.
  7. Zmień nazwę bazy danych.
  8. Ponownie włącz usługę i skieruj ją do nowej bazy danych.
alirobe
źródło
3

Opcja działająca dla mnie w tym scenariuszu jest następująca:

  1. Rozpocznij operację „Odłącz” w danej bazie danych. Spowoduje to otwarcie okna (w SQL 2005) wyświetlającego aktywne połączenia, które zapobiegają działaniom na DB.
  2. Zabij aktywne połączenia, anuluj operację odłączania.
  3. Baza danych powinna być teraz dostępna do przywracania.
Lars Timenes
źródło
W SQL 2008 Management Studio z jakiegoś powodu nie można uzyskać dostępu do aktywnego połączenia z ekranu „Odłącz”. Działa świetnie w 2005 roku i tak zawsze to robiłem, dopóki nie uaktualniliśmy się do 2008 roku, a teraz wszystko, co dostajesz, to głupia wiadomość, która każe ci zamknąć połączenie, ale nie pozwala ci otworzyć szczegółów połączenia, aby zabić każde połączenie .
Jim
2

Spróbuj tego:

ALTER DATABASE [DATABASE_NAME]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
Joseph Sturtevant
źródło
2

Kliknij prawym przyciskiem myszy nazwę bazy danych, kliknij Właściwość, aby wyświetlić okno właściwości, Otwórz kartę Opcje i zmień właściwość „Ogranicz dostęp” z Wiele użytkowników na Pojedyncze. Po naciśnięciu przycisku OK pojawi się monit o zamknięcie wszystkich otwartych połączeń, wybierz „Tak” i możesz zmienić nazwę bazy danych ....

Sanjay Saxena
źródło
2

Nie działały one dla mnie (SQL2008 Enterprise), nie widziałem też żadnych uruchomionych procesów ani użytkowników podłączonych do bazy danych. Ponowne uruchomienie serwera (kliknij prawym przyciskiem myszy Sql Server w Management Studio i wybierz Uruchom ponownie) pozwoliło mi przywrócić DB.

The Coder
źródło
2

Korzystam z programu SQL Server 2008 R2, moja baza danych została już ustawiona dla jednego użytkownika i istniało połączenie, które ograniczało wszelkie działania w bazie danych. Zatem zalecane rozwiązanie SQLMenace zareagowało błędem. Oto taki, który zadziałał w moim przypadku .

Ilmar
źródło
0

Używam sp_who, aby uzyskać listę wszystkich procesów w bazie danych. Jest to lepsze, ponieważ możesz chcieć sprawdzić, który proces zabić.

declare @proc table(
    SPID bigint,
    Status nvarchar(255),
    Login nvarchar(255),
    HostName nvarchar(255),
    BlkBy nvarchar(255),
    DBName nvarchar(255),
    Command nvarchar(MAX),
    CPUTime bigint,
    DiskIO bigint,
    LastBatch nvarchar(255),
    ProgramName nvarchar(255),
    SPID2 bigint,
    REQUESTID bigint
)

insert into @proc
exec sp_who2

select  *, KillCommand = concat('kill ', SPID, ';')
from    @proc

Wynik
Możesz użyć polecenia w kolumnie KillCommand, aby zabić żądany proces.

SPID    KillCommand
26      kill 26;
27      kill 27;
28      kill 28;
Rawitas Krungkaew
źródło
-1

Możesz użyć polecenia SP_Who i zabić cały proces korzystający z bazy danych, a następnie zmienić nazwę bazy danych.

Mehdi Lotfi
źródło