Не удалось получить эксклюзивный доступ, так как база данных используется - PullRequest
36 голосов
/ 28 октября 2010

Я использую следующий код для восстановления баз данных,

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();
    }
}

но я получаю ниже исключения

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

Как я могу это исправить?

Ответы [ 6 ]

52 голосов
/ 29 октября 2010

Восстановление может произойти только в том случае, если к базе данных нет никаких подключений (кроме вашей).Простой способ использования MS SQL Server для всех пользователей:

ALTER DATABASE [MyDB] SET Single_User WITH Rollback Immediate
GO

Теперь вы можете выполнять восстановление безнаказанно.Убедитесь, что вы вернули его в многопользовательский режим, когда закончите восстановление:

ALTER DATABASE [MyDB] SET Multi_User
GO
14 голосов
/ 29 октября 2010

Таким образом, я написал приведенный ниже метод для восстановления моей базы данных,
Я прав?

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";
    }
}
9 голосов
/ 21 июля 2013

Вы можете использовать метод объекта SMO SqlServer, чтобы заблокировать все процессы в указанной базе данных перед выполнением восстановления:

sqlServer.KillAllProcesses("databaseName");
8 голосов
/ 19 февраля 2012

Лучший подход

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 - эта опция не ожидает транзакций для завершения просто начинается откат всех открытых транзакций
  • С ROLLBACK ПОСЛЕ nnn - эта опция откатит все открытые транзакции после ожидания nnn секунд для открытых транзакций в полный. В нашем примере мы указываем, что процесс должен подождите 30 секунд, прежде чем откатывать любые открытые транзакции.

  • Когда указан RESTRICTED_USER , только члены db_owner, Роли dbcreator или sysadmin могут использовать базу данных. MULTI_USER возвращает база данных в нормальном рабочем состоянии.


2-й способ: используя ssms 2008 R2, мы можем сделать то же самое

  1. щелкните правой кнопкой мыши свойство базы данных
  2. перейти к параметрам -> последний раздел с заголовком state
  3. изменить ограничить доступ на SINGLE_USER
  4. ответьте да на этот полезный вопрос, который показывает, что этот тип действия закроет все другие соединения , и я думаю, это единственное, что мы ищем здесь, чтобы пропустить ошибку

Чтобы изменить свойства базы данных, SQL Server должен закрыть все другие соединения с базой данных. Вы уверены, что хотите изменить свойства и закрыть все другие соединения? да или нет

  1. восстановить базу данных
  2. сделать шаг 1-4, изменить Ограничить доступ вернуться к MULTI_USER

3-й способ: следующие команды также закроют все соединения.

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

теперь база данных готова к восстановлению

Подробнее ( mssqltips: получение эксклюзивного доступа для восстановления баз данных SQL Server )

1 голос
/ 10 сентября 2013
  • может быть установлено только одно соединение с базой данных.-Запустите следующую команду, чтобы увидеть, откуда поступают какие-либо повторяющиеся соединения с базой данных.

    EXEC SP_WHO2
    
  • Проверьте этот список, просматривая столбец DBName.Если база данных указана в списке, проверьте столбцы ProgramName и HostName, чтобы узнать, кто пытается подключиться.

  • Если это не служба или другое приложение, которое автоматически восстанавливает соединение и может быть отключено, запишите номер в столбце SPID, чтобы разорвать соединение, и немедленно начните резервное копирование.Замените приведенный ниже SPID только на число.

    KILL SPID RESTORE DATABASE DATABASENAME FROM DISK = 'X:\PATHTO\BACKUP.BAK' GO
    
  • Если это завершится успешно, мы можем вернуть вновь восстановленную базу данных в многопользовательский режим.

    ALTER DATABASE DATABASENAME SET MULTI_USER WITH ROLLBACK IMMEDIATE GO
    
1 голос
/ 29 октября 2010

Причина этой проблемы очевидна (соединения с базой данных в настоящее время открыты / активны), но используйте следующее (Google также, чтобы вы понимали это), и все будет хорошо:

Alter Database YOURDB   
SET SINGLE_USER With ROLLBACK IMMEDIATE
GO

Очевидно, замените YOURDDB именем вашей базы данных и запустите его для основной БД.

Да, и просто, если вы застряли в однопользовательском режиме, это отменит это:

Alter Database YOURDB   
SET MULTI_USER With ROLLBACK IMMEDIATE
GO

Надеюсь, это поможет.

EDIT:

Вы также можете следовать этому , чтобы увидеть, откуда происходят соединения, и другую информацию:

Я проверял это, имея услуги работает, что бы подключиться к база данных. Я обнаружил, что вы должны были установить Однопользовательский режим, затем запустите sp_who2 для увидеть, где было одно соединение исходя из, и обратите внимание на SPID. Вы может запустить команду kill для этого SPID и восстановление в том же сделка, и она должна пройти. Вот последовательность, которую я использовал:

ИСПОЛЬЗОВАТЬ MASTER ALTER DATABASE DATABASENAME SET SINGLE_USER с ROLLBACK НЕМЕДЛЕННЫЙ GO

-Это будет сделано, так что только одно соединение с базой данных может быть сделал. -Спустите следующую команду, чтобы увидеть, где какие-либо повторяющиеся подключения к база данных поступает из.

EXEC SP_WHO2

-Проверьте этот список, просматривая столбец DBName. Если база данных в списке проверьте имя программы и HostName столбец, чтобы увидеть, кто пытаясь подключиться. -Если это не служба или другое приложение, которое будет автоматически восстановить соединение, которое можно отключить, обратите внимание число в столбце SPID, чтобы убить соединение, и сразу же начать резервная копия. Заменить SPID ниже на просто номер.

БАЗА ДАННЫХ УБИЙСТВА SPID DATABASENAME FROM DISK = 'X: \ PATHTO \ BACKUP.BAK' GO

-Если это успешно завершено, мы можем установить вновь восстановленную базу данных вернуться в многопользовательский режим.

ALTER DATABASE DATABASENAME SET MULTI_USER с опцией ROLLBACK GO

...