web-dev-qa-db-fra.com

Base de données de restauration SQL Server avec connexions actives

J'essaie d'exécuter ce script SQL sur une instance SQL Server pour restaurer une base de données de test sur une copie plus récente de la base de données active.

RESTORE FILELISTONLY
   FROM disk = '\\staging_server\path\to\db_backup.bak'    
-- Restore the files for 
RESTORE DATABASE Test_DB
   FROM disk = '\\staging_server\path\to\db_backup.bak'
   WITH replace,
   MOVE 'Test_DB' TO 'D:\R2_BIN\Test_DB.mdf', 
   MOVE 'Test_DB_log' TO 'D:\R2_BIN\Test_DB_log.ldf', 
   stats = 5
GO

Cependant, lors de l'exécution du script, je reçois l'erreur suivante.

Msg 3101, niveau 16, état 1, ligne 5
L'accès exclusif n'a pas pu être obtenu car la base de données est en cours d'utilisation.
Msg 3013, niveau 16, état 1, ligne 5
RESTORE DATABASE se termine anormalement.

Existe-t-il un moyen de forcer l'exécution de cette opération et de supprimer toutes les connexions dont elle a besoin pour le faire? J'ai essayé de fermer toutes les applications susceptibles de se connecter à la base de données, mais je ne peux tout simplement pas identifier certaines des connexions. Il y en a plusieurs de mon nom d'utilisateur et pourtant je n'ai qu'une seule instance de SQL Server Management Studio ouverte.

Quoi qu'il en soit, existe-t-il un moyen de supprimer toutes les connexions à une base de données spécifique? Il y a pas mal de bases de données en cours d'exécution sur cette instance, donc je ne veux pas simplement arrêter et redémarrer l'instance ensemble si je peux l'aider.

8
Luke

Vous devez passer en mode mono-utilisateur:

-- Close all connections and rollback all transaction
ALTER DATABASE Test_DB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO

RESTORE FILELISTONLY
   FROM disk = '\\staging_server\path\to\db_backup.bak'    
-- Restore the files for 
RESTORE DATABASE Test_DB
   FROM disk = '\\staging_server\path\to\db_backup.bak'
   WITH replace,
   MOVE 'Test_DB' TO 'D:\R2_BIN\Test_DB.mdf', 
   MOVE 'Test_DB_log' TO 'D:\R2_BIN\Test_DB_log.ldf', 
   stats = 5
GO

ALTER DATABASE Test_DB SET MULTI_USER;
GO
11
Julien Vavasseur

Msg 3101, niveau 16, état 1, ligne 5 L'accès exclusif n'a pas pu être obtenu car la base de données est en cours d'utilisation.

Le message d'erreur dit tout. L'opération de restauration nécessite un accès exclusif à la base de données lorsque vous essayez de la restaurer à partir de la sauvegarde. Puisqu'il n'est pas en mesure d'obtenir, vous obtenez un message d'erreur.

Puisque vous restaurez sur une base de données déjà présente, vous n'avez pas besoin d'utiliser WITH MOVE commande. Ci-dessous devrait fonctionner

use master
go
alter database Test_DB set single_user with rollback immediate
go
RESTORE DATABASE Test_DB
   FROM disk = '\\staging_server\path\to\db_backup.bak'
   WITH replace
   go
1
Shanky

Tuer les sessions est quelque chose qui ne devrait pas être fait en premier lieu:

L'approche que j'utilise lors d'une restauration pendant une telle activité de rafraîchissement serait:

Approche 1:

Mettez la base de données en mode mono-utilisateur, effectuez la restauration et réinitialisez-la sur multi_user

use master
go
alter database <database_name_here>
set single_user with rollback immediate

Faites la restauration et revenez à multi_user

alter database <database_name>
set multi_user
go

Approche 2:

Si ci-dessus ne fonctionne pas: mettez la base de données hors ligne et reconnectez-la ci-dessous:

- Mettre la base de données hors ligne

ALTER DATABASE [database name] SET OFFLINE WITH
ROLLBACK IMMEDIATE
GO
-- Take the Database Online
ALTER DATABASE [myDB] SET ONLINE
GO

Approche 3: Pas la meilleure façon mais faites selon vos besoins

Affichez les sessions ouvertes de la base de données à l'aide de SP_who2 ou SP_whoisactive et supprimez les sessions que vous analysez devraient être sans aucun impact.

ou utilisez le script ci-dessous pour tuer toutes les sessions ouvertes pour cette base de données:

declare @sql as varchar(20), @spid as int
select @spid = min(spid)  from master..sysprocesses  where dbid = db_id('<database_name>') 
and spid != @@spid    

while (@spid is not null)
begin
    print 'Killing process ' + cast(@spid as varchar) + ' ...'
    set @sql = 'kill ' + cast(@spid as varchar)
    exec (@sql)

    select 
        @spid = min(spid)  
    from 
        master..sysprocesses  
    where 
        dbid = db_id('<database_name>') 
        and spid != @@spid
end 

print 'Process completed...'
1
KASQLDBA