Comment exclure des utilisateurs d'une base de données SQL Server 2008?


22

Nous devons effectuer une restauration, et nous ne pouvons pas le faire car d'autres utilisateurs sont connectés. Nous pensions avoir déconnecté chaque processus, mais apparemment pas.

Comment pouvons-nous, à partir de Management Studio, lancer tout le monde pour que nous puissions faire cette sauvegarde?

Réponses:


25

Il y a deux façons de procéder:

  1. Cliquez avec le bouton droit sur la base de données dans l'Explorateur d'objets, accédez à Tâches> Détacher. Cochez la case Supprimer les connexions.

  2. Réglez la base de données en mode mono-utilisateur comme indiqué ici :

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

Je ne savais pas que j'avais tant de commentaires lol. Marian est correcte, pas besoin d'exécuter le détachement réel, il suffit d'obtenir le script pour tuer les utilisateurs. @NickChammas Oui, le faire en lecture seule empêche les utilisateurs de se reconnecter. Lorsque vous le définissez multi-utilisateurs, vous pouvez effectuer la restauration. Les noms de base de données proviennent également d'un modèle et, à ce titre, les balises telles que «<Nom de la base de données, nom système>» sont destinées à être remplacées par l'utilisation de Ctrl + Maj + M. Dans un script non basé sur un modèle, les dbnames n'auraient pas de guillemets autour d'eux.
Wil

43

J'utilise toujours ce qui suit:

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;

Parfois, cela peut prendre un certain temps et parfois il est bloqué parce que c'est vous qui l'exécutez et que vous avez une connexion active à la base de données . Recherchez d'autres fenêtres de requête pouvant avoir le même contexte de base de données - cela peut inclure des boîtes de dialogue ouvertes, l'Explorateur d'objets, IntelliSense, des travaux de longue durée, etc.

Quand j'ai fini d'apporter mes modifications à la configuration de cette base de données, j'ai simplement:

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

Bien que, parfois, la chose que je dois faire pour cette base de données nécessite que la base de données soit en ligne, donc parfois je dois la laisser en mode mono-utilisateur et faire ceci:

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

Maintenant, je peux apporter mes modifications, puis lorsque je suis prêt à connecter d'autres utilisateurs, simplement:

ALTER DATABASE [dbname] SET MULTI_USER;

2

Je règle normalement la base de données dans single_user, puis j'attends le délai, puis je remets la base de données en multi-utilisateur comme ci-dessous:

-- 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'

En fait, il n'est pas nécessaire de "définir plusieurs utilisateurs", car vous exécutez un seul script (transaction) avec l'instruction restore. La restauration avec récupération se chargera de remettre la base de données en mode multi-utilisateur.
Svein Terje Gaup

1

Aucune des options ci-dessus n'a fonctionné pour moi car le serveur a été martelé par plusieurs tentatives de connexion à distance.

Lorsque j'ai fermé le port de base de données spécifique sur le pare-feu Windows, la fonction normale Alter .. Set Multi_User a fonctionné lors de la première tentative.


-1

Ce qui suit tue en fait toutes les connexions. Très utile dans les cas où la configuration du mode utilisateur unique échoue

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)

1
Cela ne fonctionne pas car sysprocessesne tient pas toujours compte de toutes les sessions qui pourraient contenir des verrous dans cette base de données (pensez au scénario simple où une requête est exécutée dans le contexte de la base de données A mais joint une table dans A et une table dans B) .
Aaron Bertrand

-1

Vous pouvez utiliser le script ci-dessous pour neutraliser tout le monde ou le modifier pour une base de données spécifique.

Tout ce qui peut être tué, le sera! Les SPID du service SQL ne seront cependant pas affectés.

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

-3

J'utilise ce code:

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

Mais je peux voir que l'exemple SINGLE USER est moins à taper.


3
La remise en ligne de la base de données signifie également que les autres utilisateurs peuvent se reconnecter avant de démarrer votre restauration.
Aaron Bertrand
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.