2010-10-28 2 views
33

J'utilise le code ci-dessous pour restaurer les bases de données,Un accès exclusif ne pouvait pas être obtenue parce que la base de données est en cours d'utilisation

void Restore(string ConnectionString, string DatabaseFullPath, string backUpPath) 
{ 
    string sRestore = 
     "USE [master] RESTORE DATABASE [" + DatabaseFullPath + "] FROM DISK = N'" + backUpPath + "' WITH FILE = 1, NOUNLOAD, STATS = 10"; 

    using (SqlConnection con = new SqlConnection(ConnectionString)) 
    { 
     con.Open(); 
     SqlCommand cmdBackUp = new SqlCommand(sRestore, con); 
     cmdBackUp.ExecuteNonQuery(); 
    } 
} 

mais je reçois ci-dessous exception

"Exclusive access could not be obtained because the database is in use. 
RESTORE DATABASE is terminating abnormally. 
Changed database context to 'master'." 

Comment puis-je résoudre ce problème?

Répondre

48

Une restauration ne peut se produire si la base de données n'a pas de connexions à elle (en plus de la vôtre). La façon facile sur un serveur MS SQL pour lancer tous les utilisateurs est hors:

ALTER DATABASE [MyDB] SET Single_User WITH Rollback Immediate 
GO 

Maintenant, vous pouvez effectuer votre restauration en toute impunité. Assurez-vous que vous réglez de nouveau en mode multi-utilisateur lorsque vous avez terminé la restauration:

ALTER DATABASE [MyDB] SET Multi_User 
GO 
+0

Ma base de données est dans 'D: \ SQL \ RRDB.mdf', je dois remplacer' MyDB' par le chemin complet ou juste 'RRDB.mdf'? –

+0

Vous devriez juste avoir besoin de RRDB. – KeithS

+0

Dans la réponse suivante, j'ai utilisé le chemin complet et cela a fonctionné. –

1

La raison de cette question est de soi (connexions à la base de données actuellement ouvert/actif), mais utiliser les éléments suivants (google aussi si vous le comprenez) et ce sera bien:

Alter Database YOURDB 
SET SINGLE_USER With ROLLBACK IMMEDIATE 
GO 

De toute évidence, remplacez le YOURDDB par le nom de votre base de données et exécutez-le par rapport à la base de données principale.

Oh, et juste Incase, si vous obtenez 'coincé' en mode utilisateur unique, cela défaire:

Alter Database YOURDB 
SET MULTI_USER With ROLLBACK IMMEDIATE 
GO 

Hope this helps.

EDIT:

Vous pouvez également suivre this, pour voir où les connexions sont à partir, et d'autres informations:

J'ai testé cela tout en ayant des services marchepieds qui se reconnecter à la base de données . J'ai trouvé que vous deviez mettre à Mode mono-utilisateur, puis exécutez sp_who2 à voir où la seule connexion était provenant de, et notez le SPID. Vous pouvez exécuter la commande kill pour ce SPID et la restauration dans la même transaction , et il doit passer par. Voici la séquence je:

USE MASTER ALTER DATABASE DATABASENAME SET SINGLE_USER AVEC ROLLBACK IMMEDIATE GO

-Ce fera en sorte qu'une seule connexion à la base de données peut être faite. - Exécutez la commande suivante pour voir d'où proviennent les connexions récurrentes à la base de données .

EXEC sp_who2

-Check cette liste, la recherche dans la colonne DBName. Si la base de données est répertoriée, vérifiez la colonne ProgramName et HostName pour voir qui est essayant de se connecter. -S'il ne s'agit pas d'un service ou d'une autre application qui se reconnecterait automatiquement et qui peut être arrêtée, notez le numéro dans la colonne SPID pour tuer la connexion et commencer immédiatement la sauvegarde . Remplacez SPID ci-dessous par juste le nombre.

KILL SPID RESTORE BASE DE DONNÉES DATABASENAME FROM DISK = 'X: \ PATHTO \ BACKUP.BAK 'GO

-Si cela se termine avec succès, nous pouvons rétablir la base de données nouvellement restaurée en mode multi-utilisateur.

ALTER DATABASE DATABASENAME SET MULTI_USER AVEC ROLLBACK IMMEDIATE GO

+0

-1 pour plagiat. Le texte sous EDIT est copié directement à partir de la réponse de TheOneBlackMage [ici] (http://social.msdn.microsoft.com/Forums/en-US/sqldisasterrecovery/thread/aad41cbb-10cb-4109-9e55-aab048bbeb9d). –

+0

"Appelez la police Internet, j'ai fait une erreur et maintenant je cite des sites Web pour essayer de me racheter" <- Joe Stefanelli, 28/10/2010 EDIT: Il a supprimé son commentaire, et m'a laissé downvoted. LOL – Dave

+0

1. En regardant l'historique d'édition, vous avez ajouté le lien hypertexte * après * J'ai posté mon commentaire. 2. Une idée de pourquoi j'ai reçu 4 downvotes sur certaines de mes autres réponses immédiatement après avoir posté mon commentaire? –

14

ainsi que je l'ai écrit la méthode ci-dessous pour restaurer ma base de données,
Suis-je dans le bon sens?

void Restore(string ConnectionString, string DatabaseFullPath, string backUpPath) 
{ 
    using (SqlConnection con = new SqlConnection(ConnectionString)) 
    { 
     con.Open(); 

     string UseMaster = "USE master"; 
     SqlCommand UseMasterCommand = new SqlCommand(UseMaster, con); 
     UseMasterCommand.ExecuteNonQuery(); 

     string Alter1 = @"ALTER DATABASE [" + DatabaseFullPath + "] SET Single_User WITH Rollback Immediate"; 
     SqlCommand Alter1Cmd = new SqlCommand(Alter1, con); 
     Alter1Cmd.ExecuteNonQuery(); 

     string Restore = @"RESTORE DATABASE [" + DatabaseFullPath + "] FROM DISK = N'" + backUpPath + @"' WITH FILE = 1, NOUNLOAD, STATS = 10"; 
     SqlCommand RestoreCmd = new SqlCommand(Restore, con); 
     RestoreCmd.ExecuteNonQuery(); 

     string Alter2 = @"ALTER DATABASE [" + DatabaseFullPath + "] SET Multi_User"; 
     SqlCommand Alter2Cmd = new SqlCommand(Alter2, con); 
     Alter2Cmd.ExecuteNonQuery(); 

     labelReport.Text = "Successful"; 
    } 
} 
+0

me semble bon, en principe. Je ne suis pas capable de l'exécuter, mais il n'y a pas d'erreurs flagrantes. Gardez à l'esprit que le 'set single user with rollback immediate' fermera toutes les connexions (à l'exception de celle qui exécute la commande) et annulera toutes les transactions. – Dave

8

La meilleure approche

Alter Database <Db_Name> SET [SINGLE_USER | RESTRICTED_USER] 
With ROLLBACK [IMMEDIATE | AFTER 30] 
go 
--do your job that needs exclusive access 
go 
--Back to normal mode 
Alter Database <Db_Name> SET MULTI_USER 
  • ROLLBACK IMMEDIATE - cette option ne pas attendre pour les transactions pour le compléter commence juste reculer toutes les transactions ouvertes
  • AVEC ROLLBACK APRES nnn - cette option wi ll rollback toutes les transactions ouvertes après avoir attendu nnn secondes pour les transactions ouvertes à terminé. Dans notre exemple, nous spécifions que le processus doit attendre 30 secondes avant d'annuler toute transaction ouverte.

  • Lorsque RESTRICTED_USER est spécifié, seuls les membres du db_owner, dbcreator ou sysadmin rôles peuvent utiliser la base de données. MULTI_USER renvoie la base de données à son état de fonctionnement normal.


2ème façon: en utilisant SSMS 2008 R2, nous pouvons faire la même chose

  1. propriété de base de données clic droit
  2. aller aux options -> dernière section avec en-tête de état
  3. Modifier Limiter l'accès à SINGLE_USER
  4. répondre oui à cette question utile qui montre que ce genre d'action fermer toutes les autres connexions et je suppose que c'est la seule chose que nous cherchons ici par passer l'erreur

Pour modifier les propriétés de la base de données, SQL Server doit fermer toutes les autres connexions à la base de données. Êtes-vous sûr de vouloir modifier les propriétés et fermer toutes les autres connexions? oui ou non

  1. restaurer votre base de données
  2. faire étape 1-4 changer restreindre l'accès Retour à MULTI_USER

3ème voie: les commandes suivantes fermera également toutes les connexions aussi.

ALTER DATABASE [DbName] SET OFFLINE 
go  
ALTER DATABASE [DbName] SET ONLINE 
base de données

maintenant est prêt à restaurer

Plus (mssqltips :Getting exclusive access to restore SQL Server databases)

+1

SET OFFLINE & SET ONLINE a également travaillé sur SQL 2008. Notez que les deux doivent être faits successivement; Si la base de données est hors ligne, elle ne peut pas être restaurée. –

+0

si la base de données est hors ligne, elle peut être restaurée. Je l'ai testé sur la mise à jour 2008 R2 et cela a fonctionné. En général, les méthodes mentionnées ne fonctionnent pas et vous devez utiliser le moniteur d'activité pour arrêter les sessions actives. –

6

Vous pouvez utiliser la méthode sur SMO objet SqlServer à KIIL tous les processus sur une base de données spécifiée avant d'effectuer une restauration:

sqlServer.KillAllProcesses("databaseName"); 
1
  • Une seule connexion à la base de données peut être effectuée. Exécutez la commande suivante pour voir d'où proviennent les connexions récurrentes à la base de données.

    EXEC SP_WHO2 
    
  • Cochez cette liste en regardant sous la colonne DBName. Si la base de données est répertoriée, vérifiez la colonne ProgramName et HostName pour voir qui tente de se connecter.

  • S'il ne s'agit pas d'un service ou d'une autre application qui se reconnecte automatiquement et qui peut être arrêtée, notez le numéro dans la colonne SPID pour arrêter la connexion et démarrez immédiatement la sauvegarde. Remplacez SPID ci-dessous avec juste le nombre.

    KILL SPID RESTORE DATABASE DATABASENAME FROM DISK = 'X:\PATHTO\BACKUP.BAK' GO 
    
  • Si cela se termine avec succès, nous pouvons définir la nouvelle base de données restaurés en mode multi-utilisateur.

    ALTER DATABASE DATABASENAME SET MULTI_USER WITH ROLLBACK IMMEDIATE GO 
    
Questions connexes