私は現在、一部のクラスがSQLServer2005データベースを正しく編集しているかどうかをテストする単体テストを構築しています。これを行うために、本番環境からデータの小さなサブセットを作成し、バックアップファイルとして保存しています。単体テストでデータベースの状態がクリーンであることを確認する必要がある場合は常に、基本的に次のSQLを呼び出す復元ルーチンを呼び出します。
RESTORE DATABASE database FROM DISK = 'c:\test\backup.bak' WITH REPLACE, NORECOVERY
これは通常は機能し、まともな速度です。私が通常言うとき、それは時々データベースが「復元」モードでスタックし、次のようなエラーメッセージが表示されるためです(Alterコマンドであると仮定します):
ALTER DATABASE is not permitted while a database is in the Restoring state.
これは、最初が失敗した場合、すべてのテストが失敗することを意味します。データベースをスタック状態から抜け出すことはできますが、毎回それを行うのはかなり苛立たしく、非常に時間がかかり、単体テストの全体的なポイントがあったため、テストをアクティブ化するときに何も必要ありませんでした。
RESTORE構文で回避できるかどうかを確認しようとしましたが、問題を解決できると思われるオプションやフラグを並べ替えることができません。
RESTOREコマンドよりもはるかに安全な他の方法を使用できますか?
更新: 接続がまだアクティブなときに復元が失敗することがほとんどであることがわかりました。私は通常、次の構造でその問題を処理しました。
ALTER DATABASE MyDatabase SET Single_User WITH Rollback Immediate
-- Restore logic here
ALTER DATABASE MyDatabase SET Multi_User
これに伴う問題は、すべての接続が1つに制限されるだけであるということです。時々、閉じることを余儀なくされた接続の1つが、1つだけの空きにジャンプして、復元を中断し、失敗させます(または、これを読んでいるドキュメントやページから収集できます)。
代わりに、復元ロジックを開始する前に、次のSQLコマンドを実行しようとしています。
Declare @spid int
Select @spid = min(spid) from master.dbo.sysprocesses
where dbid = db_id('Mydatabase')
While @spid Is Not Null
Begin
Execute ('Kill ' + @spid)
Select @spid = min(spid) from master.dbo.sysprocesses
where dbid = db_id('Mydatabase') and spid > @spid
End
-- Do Restore Logic
コードのこのセクションに入り、すべての接続をアクティブに閉じます。これにより、復元ロジックに実行の余地が与えられます。ただし、これが最善の方法であるかどうかは完全にはわかりません。接続の再確立が妨げられず、復元プロセスが再び中断される可能性があるためです。しかし、これまでのところ、これが起こったという証拠はまだ見ていません。