Wie können Sie alle aktuellen Verbindungen zu einer SQL Server 2005-Datenbank beenden?

288

Ich möchte eine Datenbank umbenennen, erhalte aber weiterhin den Fehler, dass die Datenbank nicht exklusiv gesperrt werden konnte, was bedeutet, dass noch einige Verbindungen aktiv sind.

Wie kann ich alle Verbindungen zur Datenbank beenden, um sie umzubenennen?

Adam
quelle

Antworten:

378

Der Grund, warum der von Adam vorgeschlagene Ansatz nicht funktioniert, ist, dass während der Zeit, in der Sie die aktiven Verbindungen durchlaufen, eine neue hergestellt werden kann und Sie diese vermissen werden. Sie können stattdessen den folgenden Ansatz verwenden, der diesen Nachteil nicht aufweist:

-- 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
quelle
1
Das scheint für SQL Server 2008 nicht zu funktionieren ... Hier ist der Fehler, den ich erhalten habe: Konsole: Meldung 102, Ebene 15, Status 1, Zeile 4 Falsche Syntax in der Nähe von '-'. Meldung 319, Ebene 15, Status 1, Zeile 4 Falsche Syntax in der Nähe des Schlüsselworts 'mit'. Wenn diese Anweisung ein allgemeiner Tabellenausdruck, eine xmlnamespaces-Klausel oder eine Änderungsverfolgungskontextklausel ist, muss die vorherige Anweisung mit einem Semikolon abgeschlossen werden. Meldung 102, Ebene 15, Status 1, Zeile 4 Falsche Syntax in der Nähe von 'IMMEDIATE'. Befehl: ALTER DATABASE ASMR-wdanda SET SINGLE_USER MIT ROLLBACK IMMEDIATE
Wagner da Silva
Ich habe dies gerade 2008 ohne Probleme ausgeführt. ALTER DATABASE aspnetdb SET SINGLE_USER MIT ROLLBACK IMMEDIATE select GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER Was hast du anstelle des auskommentierten Codes?
SQLMenace
Arbeitete für mich mit SQL Server 2008 und SQL Express-Instanz.
Tim Murphy
19
@ Wagner, wenn die Datenbank ein '-' im Namen hat, müssen Sie Klammern verwenden: ALTER DATABASE [foo-bar] SET SINGLE_USER MIT ROLLBACK IMMEDIATE
Ben Challenor
14
Bitte beachten Sie - Versuchen Sie dies NICHT auf dem auf Amazon RDS gehosteten SQL Server. Sie können die Datenbank nicht auf den MULTI_USER-Modus zurücksetzen. Stellen Sie sicher, dass Sie über einen anderen Satz von DBA-Anmeldeinformationen verfügen, bevor Sie dies versuchen. Ich habe dies behoben, indem ich zu einem der vorherigen Schnappschüsse zurückgekehrt bin. Einige Daten verloren. Zum Glück waren die Daten nicht kritisch.
RuntimeException
110

Um dies zu erreichen, ersetzen Sie 'DB_NAME' durch die Datenbank, um alle Verbindungen zu beenden:

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
quelle
1
Dies funktionierte für mich, fügte ich and spid <> @@SPIDder SELECT @sKillConnectionAnweisung hinzu , damit nicht versucht wurde, meine aktuelle Verbindung zu beenden, was zu einer Fehlermeldung führen würde.
Luis Perez
Es können nur Benutzerprozesse beendet werden, die immer noch blockiert sind und den Multi-User-Modus aufgrund eines Deadlocks nicht wiederherstellen können.
rainabba
mateuscb - die einzige Möglichkeit, unter mssql 10.00 nicht zu funktionieren, besteht darin, dass Sie einen Datenbanknamen haben, für den [] erforderlich ist, und diese nicht verwenden. ALTER DATABASE [YourDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE funktioniert in 10, 10.5, 11 und 12.
Jeremy
Lebensretter. Sollte die beste Antwort sein.
gls123
55

Töte es und töte es mit Feuer:

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
quelle
27

Verwenden von SQL Management Studio Express:

Klicken Sie in der Baumstruktur des Objekt-Explorers unter Verwaltung auf "Aktivitätsmonitor" (wenn Sie ihn dort nicht finden, klicken Sie mit der rechten Maustaste auf den Datenbankserver und wählen Sie "Aktivitätsmonitor" aus). Durch Öffnen des Aktivitätsmonitors können Sie alle Prozessinformationen anzeigen. Sie sollten in der Lage sein, die Sperren für die Datenbank zu finden, an der Sie interessiert sind, und diese Sperren aufzuheben, wodurch auch die Verbindung unterbrochen wird.

Danach sollten Sie umbenennen können.

Joseph Daigle
quelle
Ich sehe dieses Element "Aktivitätsmonitor" nicht unter "Verwaltung". Vielleicht liegt es auch daran, dass ich SQL 2008 verwende.
Wagner da Silva
14
Ich habe eine "Aktivität Montior" gefunden, wenn Sie mit der rechten Maustaste auf den SERVER klicken, nicht auf die DB. Sie können dann die Registerkarte "Prozesse" auswählen und nach Datenbank filtern.
Alirobe
Anscheinend müssen Sie blockierte Prozesse einzeln beenden, aber es ist eine einfache Methode, die keine lokale Anmeldung oder den Ausfall des gesamten Datenbankservers erfordert.
Álvaro González
24

Ich habe immer verwendet:


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
quelle
21
ALTER DATABASE [Test]
SET OFFLINE WITH ROLLBACK IMMEDIATE

ALTER DATABASE [Test]
SET ONLINE
Santhosh Kumar
quelle
14

Offline zu nehmen dauert eine Weile und manchmal habe ich Probleme damit ..

Meiner Meinung nach der solideste Weg:

Trennen Klicken Sie mit der rechten Maustaste auf DB -> Aufgaben -> Trennen ... aktivieren Sie "Verbindungen trennen"

Erneutes Anhängen Klicken Sie mit der rechten Maustaste auf Datenbanken -> Anhängen .. Hinzufügen ... -> wählen Sie Ihre Datenbank aus und ändern Sie die Spalte Anhängen als in den gewünschten Datenbanknamen. OK

NJV
quelle
Mag ich. Der schnellste Weg, dies sicher über die GUI zu tun.
Whelkaholism
Es wirkt wie ein Zauber! Der einfache Weg ist der gute Weg. Vielen Dank.
Schlepper stark
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

Verwenden Sie die 'Master'-Datenbank und führen Sie diese Abfrage aus. Dadurch werden alle aktiven Verbindungen aus Ihrer Datenbank beendet.

Talha
quelle
1
Es funktioniert wirklich :) Ich würde jedoch raten, den Ausführungsteil dieses Skripts auskommentiert zu lassen und stattdessen eine print @query einzufügen, nur um sicherzugehen, dass Sie dies nicht versehentlich auf einem Produktionsserver ausführen.
Marcello Miorelli
5

Normalerweise tritt dieser Fehler auf, wenn ich versuche, eine Datenbank wiederherzustellen. Normalerweise gehe ich in Management Studio einfach zum Anfang des Baums und klicke mit der rechten Maustaste auf den Datenbankserver und starte ihn neu (da er sich auf einem Entwicklungscomputer befindet, ist dies in der Produktion möglicherweise nicht ideal ). Dies schließt alle Datenbankverbindungen.

RedWolves
quelle
Vielen Dank, dies hat funktioniert (die ALTER DATABASE ... SET SINGLE_USERBefehle in anderen Antworten haben den gleichen Fehler "Exklusive Sperre konnte nicht erhalten werden" zurückgegeben).
Tinister
4

Klicken Sie in MS SQL Server Management Studio im Objekt-Explorer mit der rechten Maustaste auf die Datenbank. Wählen Sie im folgenden Kontextmenü "Aufgaben -> Offline nehmen".

John Christensen
quelle
4
Sie können dies nicht tun, wenn eine aktive Verbindung besteht.
Alirobe
4

Ein weiterer Ansatz "Kill it with Fire" besteht darin, den MSSQLSERVER-Dienst neu zu starten. Ich mache gerne Sachen über die Kommandozeile. Wenn Sie dies genau in CMD einfügen, können Sie Folgendes tun: NET STOP MSSQLSERVER & NET START MSSQLSERVER

Oder öffnen Sie "services.msc" und suchen Sie "SQL Server (MSSQLSERVER)". Klicken Sie mit der rechten Maustaste und wählen Sie "Neustart".

Dies wird "sicher, sicher" ALLE Verbindungen zu ALLEN Datenbanken beenden, die auf dieser Instanz ausgeführt werden.

(Ich mag dies besser als viele Ansätze, die die Konfiguration auf dem Server / der Datenbank ändern und zurücksetzen)

aikeru
quelle
Was meinst du mit "nicht empfohlen"? Wenn Sie sich keine Gedanken über Verbindungen zu diesem Server machen (z. B. Debug- oder Staging-Umgebungen - oder einen Produktionsserver mit vorübergehenden Ausfallzeiten), ist dies möglicherweise der einfachste Weg. Für die Produktion - Sie möchten sich nicht mit der Konfiguration herumschlagen, wenn Sie den Dienst einfach neu starten können. Was würden Sie tun?
Aikeru
1
Ich würde mich für alles entscheiden, was NUR meine Ziel-DB betreffen sollte. Ihr Ansatz, alle DBs auf dem Zielserver zu beenden, ist nicht so klug. Aber um ehrlich zu sein, ist dies in Staging-Umgebungen vielleicht der einfachste Weg, wie Sie sagten.
Mohammed Swillam
4

So können Sie solche Dinge in MS SQL Server Management Studio 2008 zuverlässig ausführen (funktioniert möglicherweise auch für andere Versionen):

  1. Klicken Sie in der Objekt-Explorer-Struktur mit der rechten Maustaste auf den Stammdatenbankserver (mit dem grünen Pfeil), und klicken Sie dann auf Aktivitätsmonitor.
  2. Öffnen Sie die Registerkarte "Prozesse" im Aktivitätsmonitor, wählen Sie das Dropdown-Menü "Datenbanken" aus und filtern Sie nach der gewünschten Datenbank.
  3. Klicken Sie im Objekt-Explorer mit der rechten Maustaste auf die Datenbank und starten Sie eine Aufgabe 'Aufgaben -> Offline übernehmen'. Lassen Sie dies im Hintergrund laufen, während Sie ...
  4. Fahren Sie sicher herunter, was immer Sie können.
  5. Beenden Sie alle verbleibenden Prozesse auf der Registerkarte "Prozess".
  6. Schalten Sie die DB wieder online.
  7. Benennen Sie die DB um.
  8. Schalten Sie Ihren Dienst wieder online und verweisen Sie ihn auf die neue Datenbank.
Alirobe
quelle
3

Die Option, die in diesem Szenario für mich funktioniert, lautet wie folgt:

  1. Starten Sie den Vorgang "Trennen" für die betreffende Datenbank. Dadurch wird ein Fenster (in SQL 2005) geöffnet, in dem die aktiven Verbindungen angezeigt werden, die Aktionen in der Datenbank verhindern.
  2. Beenden Sie die aktiven Verbindungen und brechen Sie den Trennvorgang ab.
  3. Die Datenbank sollte jetzt zum Wiederherstellen verfügbar sein.
Lars Timenes
quelle
In SQL 2008 Management Studio können Sie aus irgendeinem Grund nicht mehr über den Bildschirm "Trennen" auf die aktive Verbindung zugreifen. Es funktioniert großartig im Jahr 2005 und so habe ich es immer gemacht, bis wir auf 2008 aktualisiert haben. Jetzt erhalten Sie nur noch eine dumme Nachricht, die Sie auffordert, Ihre Verbindung zu schließen, aber Sie können die Verbindungsdetails nicht öffnen, um jede Verbindung zu beenden .
Jim
2

Versuche dies:

ALTER DATABASE [DATABASE_NAME]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
Joseph Sturtevant
quelle
2

Klicken Sie mit der rechten Maustaste auf den Datenbanknamen, klicken Sie auf Eigenschaft, um das Eigenschaftenfenster abzurufen. Öffnen Sie die Registerkarte Optionen und ändern Sie die Eigenschaft "Zugriff einschränken" von "Mehrbenutzer" in "Einzelbenutzer". Wenn Sie auf OK klicken, werden Sie aufgefordert, alle offenen Verbindungen zu schließen. Wählen Sie "Ja" und Sie können die Datenbank umbenennen.

Sanjay Saxena
quelle
2

Diese funktionierten bei mir nicht (SQL2008 Enterprise), ich konnte auch keine laufenden Prozesse oder Benutzer sehen, die mit der Datenbank verbunden waren. Durch einen Neustart des Servers (Klicken Sie in Management Studio mit der rechten Maustaste auf SQL Server und wählen Sie Neu starten) konnte ich die Datenbank wiederherstellen.

Der Codierer
quelle
0

Ich benutze sp_who, um eine Liste aller Prozesse in der Datenbank zu erhalten. Dies ist besser, da Sie möglicherweise überprüfen möchten, welcher Prozess beendet werden soll.

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

Ergebnis
Sie können den Befehl in der KillCommand-Spalte verwenden, um den gewünschten Prozess abzubrechen.

SPID    KillCommand
26      kill 26;
27      kill 27;
28      kill 28;
Rawitas Krungkaew
quelle
-1

Sie können den Befehl SP_Who verwenden und alle Prozesse beenden, die Ihre Datenbank verwenden, und dann Ihre Datenbank umbenennen.

mehdi lotfi
quelle