Wie können Benutzer aus einer SQL Server 2008-Datenbank ausgeschlossen werden?

22

Wir müssen eine Wiederherstellung durchführen und können dies nicht, da andere Benutzer verbunden sind. Wir dachten, wir hätten jeden Prozess unterbrochen, aber anscheinend nicht.

Wie können wir von Management Studio aus alle anderen anstoßen, damit wir diese Sicherung durchführen können?

Daniel Williams
quelle

Antworten:

25

Es gibt zwei Möglichkeiten:

  1. Klicken Sie im Objekt-Explorer mit der rechten Maustaste auf die Datenbank und wählen Sie Aufgaben> Trennen. Aktivieren Sie das Kontrollkästchen Verbindungen trennen.

  2. Setzen Sie die Datenbank wie hier beschrieben in den Einzelbenutzermodus :

    -- hit Ctrl+Shift+M in SSMS to fill in the template parameter
    USE master;
    GO
    
    ALTER DATABASE N'<Database Name, sysname,>'
    SET SINGLE_USER
    WITH ROLLBACK IMMEDIATE;
    GO
    
    ALTER DATABASE N'<Database Name, sysname,>'
    SET READ_ONLY;
    GO
    
    ALTER DATABASE N'<Database Name, sysname,>'
    SET MULTI_USER;
    GO
    
Wil
quelle
Wusste nicht, dass ich so viele Kommentare hatte lol. Marian ist korrekt, es ist nicht erforderlich, die eigentliche Trennung auszuführen, sondern nur das Skript zum Beenden von Benutzern zu verwenden. @NickChammas Ja, wenn es schreibgeschützt ist, können die Benutzer keine Verbindung mehr herstellen. Wenn Sie es für mehrere Benutzer festlegen, können Sie die Wiederherstellung durchführen. Auch die Datenbanknamen stammen aus einer Vorlage, und als solche sollen die Tags wie '<Datenbankname, sysname>' durch die Verwendung von Strg + Umschalt + M ersetzt werden. In einem Skript ohne Vorlage werden die DB-Namen nicht in Anführungszeichen gesetzt.
Wil
43

Ich benutze immer folgendes:

USE master; -- get out of dbname myself
GO
-- kick all other users out:
ALTER DATABASE [dbname] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
-- prevent sessions from re-establishing connection:
ALTER DATABASE [dbname] SET OFFLINE;

Manchmal kann dies eine Weile dauern, und manchmal ist es blockiert, weil Sie derjenige sind, der es ausführt, und Sie haben eine aktive Verbindung zur Datenbank . Suchen Sie nach anderen Abfragefenstern, die möglicherweise denselben Datenbankkontext aufweisen. Dies kann geöffnete Dialogfelder, Objekt-Explorer, IntelliSense, Jobs mit langer Laufzeit usw. umfassen.

Wenn ich meine Änderungen an der Konfiguration dieser Datenbank vorgenommen habe, gehe ich einfach folgendermaßen vor:

ALTER DATABASE [dbname] SET ONLINE;
ALTER DATABASE [dbname] SET MULTI_USER;

Manchmal muss die Datenbank online sein, damit ich diese Datenbank bearbeiten kann. Manchmal muss ich sie also im Einzelbenutzermodus belassen und Folgendes ausführen:

ALTER DATABASE [dbname] SET ONLINE;
GO
USE [dbname];

Jetzt kann ich meine Änderungen vornehmen und dann, wenn andere Benutzer eine Verbindung herstellen können, einfach:

ALTER DATABASE [dbname] SET MULTI_USER;
Aaron Bertrand
quelle
2

Normalerweise setze ich die Datenbank in single_user und warte dann auf die Verzögerung und setze die Datenbank dann wie folgt in multiuser zurück:

-- to kill all connections for particular db ... otherwise the restore will fail as exclusive lock cannot be obtained for the db being restored.

    alter database db_name
    set single_user with rollback immediate
    waitfor delay '00:00:05'  -- wait for 5 secs
    alter database db_name
    set multi_user
    restore database db_name from disk = 'D:\restore\db_name.bak'
    with replace, stats = 10, recovery -- if you want to recover your database online
    -- optional if you dont have the same directory/file structure
    move 'datafile logical name' to 'E:\data\physical_name.mdf',
    move 'logfile logical name' to 'F:\log\physical_name_log.ldf'
Kin Shah
quelle
Tatsächlich ist es nicht erforderlich, "multi_user" festzulegen, da Sie mit der restore-Anweisung ein einzelnes Skript (Transaktion) ausführen. Bei der Wiederherstellung mit Wiederherstellung wird die Datenbank wieder in den Mehrbenutzermodus versetzt.
Svein Terje Gaup
1

Keine der oben genannten Optionen hat bei mir funktioniert, da der Server von mehreren Remoteverbindungsversuchen heimgesucht wurde.

Als ich den spezifischen Datenbank-Port auf der Windows-Firewall schloss, funktionierte der normale Alter .. Set Multi_User im ersten Versuch.

olafk
quelle
-1

Das Folgende beendet tatsächlich alle Verbindungen. Sehr nützlich in Fällen, in denen die Einstellung des Einzelbenutzermodus fehlschlägt

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)
Betty
quelle
1
Dies funktioniert nicht, da sysprocessesnicht immer alle Sitzungen berücksichtigt werden, die möglicherweise Sperren in dieser Datenbank enthalten (denken Sie an das einfache Szenario, in dem eine Abfrage im Kontext von Datenbank A ausgeführt wird, aber eine Tabelle in A und eine Tabelle in B verknüpft). .
Aaron Bertrand
-1

Sie können das folgende Skript verwenden, um entweder alle Benutzer zu nuken oder für eine bestimmte Datenbank zu ändern.

Alles, was getötet werden kann, wird es sein! SQL-Service-SPIDs sind jedoch nicht betroffen.

Drop table #who

go 

Create table #who(  [spid] int,
                    [ECID] int,
                    [Status] varchar(100),
                    [Loginname] varchar(200),
                    [Hostname] varchar(200),
                    [blk] bit,
                    dbname varchar(200),
                    cmd varchar(1000),
                    requestID int
                  )

go

Insert into #who (Spid, ECID, Status, Loginname, hostname,blk, dbname, cmd, requestid)
exec sp_who

Declare cursKillUsers Cursor for Select 'Kill ' + cast(spid as varchar(100)) + ';' [SQL] from #who where dbname like '%'
Declare @sql varchar(200)
Open cursKillUsers
Fetch next from cursKillUsers into @sql
While @@fetch_status = 0 
begin

    print @sql
    Exec (@sql)
    Fetch next from cursKillUsers into @sql

end

close cursKillUsers
deallocate cursKillUsers
BITSYSUK
quelle
-3

Ich benutze diesen Code:

ALTER DATABASE [Dbname] set offline with rollback immediate
GO
ALTER DATABASE [Dbname] set online
GO

Aber ich kann sehen, dass das SINGLE USER-Beispiel weniger zu tippen ist.

Paul Els
quelle
3
Wenn Sie die Datenbank auch wieder online stellen, können andere Benutzer die Verbindung wiederherstellen, bevor Sie mit der Wiederherstellung beginnen.
Aaron Bertrand