Erreur - L'accès exclusif n'a pas pu être obtenu car la base de données est en cours d'utilisation

119

J'essaie en fait de créer un script (dans Sql Server 2008) pour restaurer une base de données à partir d'un fichier de sauvegarde. J'ai créé le code suivant et j'obtiens une erreur -

Msg 3101, Level 16, State 1, Line 3
Exclusive access could not be obtained because 
the database is in use.
Msg 3013, Level 16, State 1, Line 3
RESTORE DATABASE is terminating abnormally.

Comment résoudre ce problème?

IF DB_ID('AdventureWorksDW') IS NOT NULL 
BEGIN 
RESTORE DATABASE [AdventureWorksDW] 
FILE = N'AdventureWorksDW_Data' 
FROM  
DISK = N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\Backup\AdventureWorksDW.bak' 
WITH  FILE = 1, 
MOVE N'AdventureWorksDW_Data' 
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW.mdf', 
MOVE N'AdventureWorksDW_Log'  
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW_0.LDF', 
NOUNLOAD,  STATS = 10 
END
Vapeur
la source
Si je peux faire fonctionner cela, je peux peut-être créer un script fiable pour restaurer plusieurs bases de données à partir d'un dossier. Je n'ai trouvé aucun code fiable sur le net. Mon code peut être fiable car il est généré par SS lui-même.
Steam

Réponses:

106

Je suppose que si vous restaurez une base de données, vous ne vous souciez pas des transactions existantes sur cette base de données. Droite? Si tel est le cas, cela devrait fonctionner pour vous:

USE master
GO

ALTER DATABASE AdventureWorksDW
SET SINGLE_USER
--This rolls back all uncommitted transactions in the db.
WITH ROLLBACK IMMEDIATE
GO

RESTORE DATABASE AdventureWorksDW
FROM ...
...
GO

Maintenant, un élément supplémentaire à prendre en compte. Après avoir défini la base de données en mode utilisateur unique, quelqu'un d'autre peut tenter de se connecter à la base de données. S'ils réussissent, vous ne pourrez pas poursuivre votre restauration. C'est une course! Ma suggestion est d'exécuter les trois déclarations à la fois.

Dave Mason
la source
les trois déclarations dans une transaction.
Steam
1
Mon SSMS passe en mode sans réponse chaque fois que j'essaye d'accéder à cette base de données adventureworks.
Steam
2
Il veut vraiment dire USE master, non USER master.
async
7
Ajoutez simplement ALTER DATABASE [AdventureWorksDW] SET MULTI_USERà la fin pour vous assurer que la base de données est de retour en mode multi-utilisateur normal.
gnaanaa
1
@gnaanaa: Si la base de données sauvegardée était en SINGLE_USERmode au moment de la sauvegarde, elle sera en SINGLE_USERmode lorsque la sauvegarde sera restaurée. S'il était en MULTI_USERmode au moment de la sauvegarde, il sera en MULTI_USERmode lors de sa restauration. Vous faites un excellent point: cela vaut vraiment la peine de vérifier une fois la restauration terminée. Vous pouvez également exécuter RESTORE HEADERONLY sur le support de sauvegarde et vérifier IsSingleUserou effectuer des calculs binaires sur la Flagscolonne.
Dave Mason
236
  1. Définissez le chemin pour restaurer le fichier.
  2. Cliquez sur "Options" sur le côté gauche.
  3. Décochez "Prendre la sauvegarde du journal de fin avant la restauration"
  4. Cochez la case - "Fermer les connexions existantes à la base de données de destination". entrez la description de l'image ici
  5. Cliquez sur OK.
Vinu M Shankar
la source
16
Dans mon cas, cette case était grisée. Cependant, j'ai recommencé et j'ai pu cocher la case avant de choisir la source à partir de laquelle restaurer. Après avoir choisi le fichier de sauvegarde, l'option était à nouveau grisée mais la case était toujours cochée et la restauration fonctionnait.
phansen
3
Félicitations pour m'avoir évité de taper SQL. La seule méthode GUI parmi toutes les réponses.
Lionet Chen
J'espère que cela aurait fonctionné pour moi comme les autres. Mais pour moi, la case à cocher est toujours restée grisée. La réponse d' Andrei Karchueuski ci- dessous a fonctionné pour moi.
Devraj Gadhavi
11
J'ai également dû décocher "Prendre la sauvegarde du journal de fin avant la restauration" avant de pouvoir restaurer.
Hylle
3
"Effectuer une sauvegarde du journal de fin avant la restauration" cela doit également être décoché. Merci
jedu
50

exécutez cette requête avant de restaurer la base de données:

alter database [YourDBName] 
set offline with rollback immediate

et celui-ci après restauration:

  alter database [YourDBName] 
  set online
Andrei Karcheuski
la source
J'ai fini par basculer vers cette méthode sur SINGLE_USER après que la connexion de l'application pilote ait battu la restauration de ma requête et l'appel MULTI_USER suivant. La restauration n'a pas pu obtenir un accès exclusif et l'ancienne base de données est restée en mode SINGLE_USER.
Smörgåsbord
3
cela a fonctionné pour moi. et il se met en ligne automatiquement une fois que vous le restaurez.
Dileep
3
Cela fonctionne, et cela évite la condition de concurrence dans la réponse acceptée.
Scott Whitlock
1
Merci Andrei.
Erdogan
11

Pour moi, la solution est:

  1. Cochez Écraser la base de données existante (AVEC REMPLACER) dans l'onglet optoins sur le côté gauche.

  2. Décochez toutes les autres options.

  3. Sélectionnez la base de données source et de destination.

  4. Cliquez sur OK.

C'est tout.

Aayush Verma
la source
1
A travaillé pour moi aussi. J'ai également dû décocher "Prendre la sauvegarde du journal de fin avant la restauration".
yuva le
7

Utilisez le script suivant pour rechercher et supprimer toutes les connexions ouvertes à la base de données avant de restaurer la 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...'

J'espère que cela aidera ...

Aqeel Haider
la source
3

Je pense qu'il vous suffit de définir la base de données en mode mono-utilisateur avant de tenter de restaurer, comme ci-dessous, assurez-vous simplement que vous utilisez master

USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER
Jason
la source
2

Je viens de redémarrer le service sqlexpress, puis la restauration s'est bien terminée

BabaNouveau
la source
que puis-je dire à propos du vote négatif ... pour moi, cela a fonctionné!
BabaNew
1
OP a eu un problème avec son script de restauration car il n'a pas pris en compte le fait que sa base de données était peut-être déjà utilisée. La solution était de mettre à jour son script avec les commandes appropriées lui permettant un accès exclusif à la base de données. Bien que le redémarrage du service ait peut-être fonctionné pour vous, ce n'était pas la solution appropriée à son problème.
PL
1
Use Master
alter database databasename set offline with rollback immediate;

--Do Actual Restore
RESTORE DATABASE databasename
FROM DISK = 'path of bak file'
WITH MOVE 'datafile_data' TO 'D:\newDATA\data.mdf',
MOVE 'logfile_Log' TO 'D:\newDATA\DATA_log.ldf',replace

alter database databasename set online with rollback immediate;
GO
Puneeth
la source
1

Solution 1: redémarrez les services SQL et essayez de restaurer la base de données Solution 2: redémarrez le système / serveur et essayez de restaurer la base de données Solution 3: récupérez la base de données actuelle, supprimez la base de données actuelle / de destination et essayez de restaurer la base de données.

Joseph Joy
la source
1

Mettre la base de données en mode mono-utilisateur n'a pas fonctionné pour moi, mais la mettre hors ligne, puis la remettre en ligne a fonctionné. C'est dans le menu contextuel de la base de données, sous Tâches.

Assurez-vous de cocher l'option «Supprimer toutes les connexions actives» dans la boîte de dialogue.

Jeffrey Harmon
la source
0

Voici une façon de restaurer la base de données de la production au développement:

REMARQUE: je le fais via le travail SSAS pour pousser la base de données de production au développement quotidiennement:

Étape 1: Supprimez la sauvegarde de la veille en développement:

declare @sql varchar(1024);

set @sql = 'DEL C:\ProdAEandAEXdataBACKUP\AE11.bak'
exec master..xp_cmdshell @sql

Étape 2: Copiez la base de données de production vers le développement:

declare @cmdstring varchar(1000)
set @cmdstring = 'copy \\Share\SQLDBBackup\AE11.bak C:\ProdAEandAEXdataBACKUP'
exec master..xp_cmdshell @cmdstring 

Étape 3: restaurer en exécutant le script .sql

SQLCMD -E -S dev-erpdata1 -b -i "C:\ProdAEandAEXdataBACKUP\AE11_Restore.sql"

Code qui se trouve dans le fichier AE11_Restore.sql:

RESTORE DATABASE AE11
FROM DISK = N'C:\ProdAEandAEXdataBACKUP\AE11.bak'
WITH MOVE 'AE11' TO 'E:\SQL_DATA\AE11.mdf',
MOVE 'AE11_log' TO 'D:\SQL_LOGS\AE11.ldf',
RECOVERY;
Non programmeur
la source
0

J'ai eu cette erreur quand il n'y avait pas assez d'espace disque pour restaurer Db. Nettoyer un peu d'espace l'a résolu.

user3790083
la source
0

mettre la base de données originale hors ligne a fonctionné pour moi

mettre hors ligne

Ali Karaca
la source