web-dev-qa-db-fra.com

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

J'utilise le code suivant pour restaurer les bases de données,

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 une exception ci-dessous

"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 le réparer?

37
Mohammad Dayyan

Une restauration ne peut se produire que si la base de données n'a pas de connexion avec elle (à part la vôtre). Le moyen simple sur un serveur MS SQL pour lancer tous les utilisateurs est:

ALTER DATABASE [MyDB] SET Single_User WITH Rollback Immediate
GO

Maintenant, vous pouvez effectuer votre restauration en toute impunité. Assurez-vous de le remettre en mode multi-utilisateur lorsque vous avez terminé la restauration:

ALTER DATABASE [MyDB] SET Multi_User
GO
52
KeithS

J'ai donc é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";
    }
}
14
Mohammad Dayyan

Vous pouvez utiliser la méthode sur l'objet SMO Sql Server pour tuer tous les processus sur une base de données spécifiée avant d'effectuer une restauration:

sqlServer.KillAllProcesses("databaseName");
9
Martin Bell

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 
  • AVEC ROLLBACK IMMÉDIATE - cette option n'attend pas pour que les transactions se terminent, il commence juste à annuler toutes les transactions ouvertes
  • AVEC ROLLBACK APRÈS nnn - cette option annulera toutes les transactions ouvertes après avoir attendu nnn secondes pour que les transactions ouvertes se terminent. Dans notre exemple, nous spécifions que le processus doit attendre 30 secondes avant d'annuler toutes les transactions ouvertes.

  • Lorsque RESTRICTED_USER est spécifié, seuls les membres des rôles db_owner, dbcreator ou sysadmin peuvent utiliser la base de données. MULTI_USER ramène 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. clic droit sur la propriété de la base de données
  2. allez dans les options -> dernière section avec un en-tête état
  3. changer Restreindre l'accès à SINGLE_USER
  4. répondez oui à cette question utile qui montre que ce type d'action va fermer toutes les autres connexions et je suppose que c'est la seule chose que nous recherchons ici pour contourner 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. Voulez-vous vraiment modifier les propriétés et fermer toutes les autres connexions? Oui ou non

  1. restaurer votre base de données
  2. faites l'étape 1-4 en changeant Restreindre l'accès retour à MULTI_USER

3ème manière: les commandes suivantes fermeront également toutes les connexions.

ALTER DATABASE [DbName] SET OFFLINE
go    
ALTER DATABASE [DbName] SET ONLINE

maintenant la base de données est prête pour la restauration

Plus ( mssqltips: Obtenir un accès exclusif pour restaurer les bases de données SQL Server )

9
Iman Abidi
  • une seule connexion à la base de données peut être établie. -Exécutez la commande suivante pour voir d'où proviennent les connexions récurrentes à la base de données.

    EXEC SP_WHO2
    
  • Vérifiez 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 reconnecterait automatiquement et qui peut être arrêtée, notez le numéro dans la colonne SPID pour interrompre la connexion et commencez immédiatement la sauvegarde. Remplacez SPID ci-dessous par juste le numéro.

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

    ALTER DATABASE DATABASENAME SET MULTI_USER WITH ROLLBACK IMMEDIATE GO
    
1
karthik

La raison de ce problème est évidente (les connexions à la base de données sont actuellement ouvertes/actives), mais utilisez ce qui suit (google aussi pour que vous le compreniez) et ça ira:

Alter Database YOURDB   
SET SINGLE_USER With ROLLBACK IMMEDIATE
GO

Évidemment, remplacez YOURDDB par le nom de votre base de données et exécutez-le sur la base de données master.

Oh, et juste au cas où, si vous le bloquiez en mode mono-utilisateur, cela l'annulerait:

Alter Database YOURDB   
SET MULTI_USER With ROLLBACK IMMEDIATE
GO

J'espère que cela t'aides.

ÉDITER:

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

J'ai testé cela lors de l'exécution de services qui se reconnecteraient à la base de données. J'ai constaté que vous deviez définir le mode mono-utilisateur, puis exécuter sp_who2 pour voir d'où provenait la connexion et noter le SPID. Vous pouvez exécuter la commande kill pour ce SPID et la restauration dans la même transaction, et elle doit être exécutée. Voici la séquence que j'ai utilisée:

UTILISER MASTER ALTER DATABASE DATABASENAME SET SINGLE_USER AVEC ROLLBACK IMMEDIATE GO

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

EXEC SP_WHO2

-Vérifiez 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. -Si ce n'est pas un service ou une autre application qui se reconnecterait automatiquement et qui peut être arrêtée, notez le numéro dans la colonne SPID pour interrompre la connexion et commencez immédiatement la sauvegarde. Remplacez SPID ci-dessous avec juste le numéro.

KILL SPID RESTORE DATABASE DATABASENAME FROM DISK = 'X:\PATHTO\BACKUP.BAK' GO

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

ALTER DATABASE DATABASENAME SET MULTI_USER WITH ROLLBACK IMMEDIATE GO

1
Dave