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


118

私は実際に1つのバックアップファイルから1つのデータベースを復元するスクリプト(SQL Server 2008)を作成しようとしています。私は次のコードを作成し、エラーが発生しています-

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.

この問題を解決するにはどうすればよいですか?

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

これを機能させることができれば、1つのフォルダーから複数のデータベースを復元するための信頼できるスクリプトを作成できるでしょう。私はネット上で信頼できるコードを見つけることができませんでした。SS自体によって生成されているため、私のコードは信頼できるかもしれません。
Steamの

回答:


105

dbを復元する場合、そのdbの既存のトランザクションは気にしないと思います。正しい?もしそうなら、これはあなたのために働くはずです:

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

ここで、もう1つ注意すべき点があります。dbをシングルユーザーモードに設定した後、他の誰かがdbに接続しようとする場合があります。成功すると、復元を続行できなくなります。レースだ!私の提案は、3つのステートメントすべてを一度に実行することです。


トランザクション内の3つのステートメントすべて。
スチーム

1
私のSSMSは、そのadventureworksデータベースにアクセスしようとするたびに、応答しないモードになります。
Steamの

2
彼は実際にはUSE master、という意味ではありませんUSER master
2015年

7
ALTER DATABASE [AdventureWorksDW] SET MULTI_USER最後に追加するだけで、データベースが通常のマルチユーザーモードに戻ります。
gnaanaa 2017

1
@gnaanaa:バックアップされたデータベースがSINGLE_USERバックアップ時にSINGLE_USERモードだった場合、バックアップが復元されるときにモードになります。それはにあった場合はMULTI_USER、バックアップ時のモード、それがになりMULTI_USER、それが復元されたときのモード。あなたは素晴らしいポイントを作ります:復元が完了した後、それは間違いなくチェックする価値があります。また、バックアップメディアでRESTORE HEADERONLYを実行IsSingleUserし、Flags列でビット単位の計算を確認または実行することもできます。
デイブメイソン

236
  1. ファイルを復元するためのパスを設定します。
  2. 左側の「オプション」をクリックします。
  3. 「復元する前にログ末尾のバックアップを取る」のチェックを外します
  4. 「宛先データベースへの既存の接続を閉じる」チェックボックスをオンにします。 ここに画像の説明を入力してください
  5. OKをクリックします。

16
私の場合、そのチェックボックスはグレー表示されていました。しかし、最初からやり直して、復元元を選択する前にチェックボックスをオンにすることができました。バックアップファイルを選択した後、オプションは再びグレー表示されましたが、ボックスはまだチェックされており、復元は機能しました。
ファンセン2017

3
SQLを入力する手間を省いてくれてありがとう。すべての回答の中で唯一のGUIメソッド。
Lionet Chen 2017

これが他の人のように私のために働いていればいいのにと思います。しかし、私にとって、チェックボックスは常に灰色のままでした。以下のAndrei Karchueuskiの 答えは私のために働いた。
Devraj Gadhavi、2018

11
復元する前に、「復元する前にログ末尾のバックアップを取る」のチェックを外さなければなりませんでした。
Hylle、2018

3
「復元する前にログ末尾のバックアップを取る」これも同様にオフにする必要があります。ありがとう
jedu

50

データベースを復元する前にこのクエリを実行します:

alter database [YourDBName] 
set offline with rollback immediate

これを復元した後:

  alter database [YourDBName] 
  set online

パイロットアプリケーションの接続がクエリの復元と後続のMULTI_USER呼び出しに勝った後、SINGLE_USERを介してこのメ​​ソッドに切り替えました。復元は排他的アクセスの取得に失敗し、古いデータベースはSINGLE_USERモードのままでした。
バイキング

3
これは私のために働いた。復元すると、自動的にオンラインになります。
Dileep

3
これは機能し、受け入れられた回答の競合状態を回避します。
スコットウィットロック2017

1
アンドレイ、ありがとう。
Erdogan

11

私にとっての解決策は:

  1. 左側の[オプトイン]タブで[既存のデータベースを上書きする(置換あり)]をオンにします。

  2. 他のすべてのオプションをオフにします。

  3. ソースおよび宛先データベースを選択します。

  4. OKをクリックします。

それでおしまい。


1
私のためにも働いた。「復元前にログ末尾のバックアップを取る」のチェックも外す必要がありました。
ユバ2018

7

次のスクリプトを使用して、データベースを復元する前に、開いているデータベースへの接続をすべて見つけて強制終了します。

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

これが役に立てば幸い...


3

以下のように、復元を試みる前にdbをシングルユーザーモードに設定する必要があるだけだと思います。 master

USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER

2

sqlexpressサービスを再起動したところ、復元は正常に完了しました


反対票について私は何を言えますか...私にとってはうまくいきました!
BabaNew

1
OPは、自分のDBがすでに使用されている可能性があるという事実を考慮していなかったため、復元スクリプトに問題がありました。解決策は、DBへの排他的アクセスを許可する適切なコマンドでスクリプトを更新することでした。サービスを再起動するとうまくいくかもしれませんが、それは彼の問題に対する適切な解決策ではありませんでした。
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

1

解決策1:SQLサービスを再起動してDBの復元を試みます解決策2:システム/サーバーを再起動してDBの復元を試みます解決策3:現在のDBを元に戻し、現在の/宛先DBを削除してDBの復元を試みます。


1

DBをシングルユーザーモードに設定するのはうまくいきませんでしたが、オフラインにしてからオンラインに戻すとうまくいきました。これは、DBの右クリックメニューの[タスク]にあります。

ダイアログの[すべてのアクティブな接続をドロップ]オプションを必ずチェックしてください。


0

これが、本番環境から開発環境にデータベースを復元する方法です。

注:本番データベースを開発にプッシュするために、SSASジョブを介して毎日実行しています。

ステップ1:開発中の前日のバックアップを削除します。

declare @sql varchar(1024);

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

ステップ2:運用データベースを開発にコピーします。

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

手順3:.sqlスクリプトを実行して復元する

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

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;

0

Dbを復元するのに十分なディスク領域がないときに、このエラーが発生しました。いくつかのスペースを掃除することで解決しました。


0

元のデータベースをオフラインにすることは私にとってうまくいきました

オフラインにする

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.