web-dev-qa-db-ja.com

データベースが使用中のため、排他アクセスを取得できませんでした

私はデータベースを復元するために次のコードを使用しています、

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'."

どうすれば修正できますか?

37
Mohammad Dayyan

復元は、データベースに(ユーザーのほかに)接続がない場合にのみ発生します。 MS SQL Serverですべてのユーザーを開始する簡単な方法は次のとおりです。

ALTER DATABASE [MyDB] SET Single_User WITH Rollback Immediate
GO

これで、問題なく復元を実行できます。復元が完了したら、必ずマルチユーザーモードに戻してください。

ALTER DATABASE [MyDB] SET Multi_User
GO
52
KeithS

したがって、私はデータベースを復元するために以下の方法を書きました、
私は正しい方法ですか?

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

SMO SqlServerオブジェクトのメソッドを使用して、復元を実行する前に、指定したデータベースのすべてのプロセスを強制終了できます。

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

最善のアプローチ

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 
  • WITH ROLLBACK IMMEDIATE-このオプショントランザクションが完了するのを待たないトランザクションが完了するまで、開いているすべてのトランザクションのロールバックを開始します
  • WInn ROLLBACK AFTER 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. Restrict AccessMULTI_USERに戻すステップ1-4を実行します

3番目の方法:次のコマンドもすべての接続を閉じます。

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

これで、データベースを復元する準備ができました

詳細( mssqltips:Getting exclusive access to restore SQL Server databases

9
Iman Abidi
  • データベースへの接続は1つしか確立できません。 -次のコマンドを実行して、データベースへの定期的な接続がどこから行われているかを確認します。

    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
karthik

この問題の理由は自明です(現在開いている/アクティブなデータベースへの接続)が、次を使用してください(Googleでも理解できるようにしてください)、問題ありません。

Alter Database YOURDB   
SET SINGLE_USER With ROLLBACK IMMEDIATE
GO

明らかに、YOURDDBをデータベースの名前に置き換え、それをマスターDBに対して実行します。

ああ、念のために言っておくと、シングルユーザーモードで「スタック」してしまった場合は、元に戻します。

Alter Database YOURDB   
SET MULTI_USER With ROLLBACK IMMEDIATE
GO

お役に立てれば。

編集:

this をたどって、接続元を確認することもできます。

データベースに再接続するサービスを実行しているときにこれをテストしました。シングルユーザーモードに設定してから、sp_who2を実行して、1つの接続の送信元を確認し、SPIDをメモする必要があることがわかりました。そのSPIDのkillコマンドと復元を同じトランザクションで実行できます。これが私が使ったシーケンスです:

MASTER ALTER DATABASE DATABASENAME SET SINGLE_USER with ROLLBACK IMMEDIATE GOを使用する

-これにより、データベースへの接続を1つだけ確立できるようになります。 -次のコマンドを実行して、データベースへの定期的な接続がどこから行われているかを確認します。

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
Dave