SQL Server 2014の運用インスタンスがあり、簡単なメンテナンスが必要です。
基本的に、1つのトランザクション内で2つのテーブル全体の内容を置き換える必要があります。データの変更が行われている間、誰もがどちらのテーブルにもクエリを実行できないようにしたいと思います。テーブルは小さく、操作には数秒もかかりません。
残念ながら、これには計画的なダウンタイムのメリットはありません。
だから問題は、一度に複数のオブジェクト、またはデータベース全体をロックするにはどうすればよいですか?
理想的には、データベースレベルのロックを取得し、変更を加えて、ロックを解放するだけで済みますが、SQL Server 2014ではそれができないようです。
最初にUPDLOCKでクエリを使用して、トランザクション全体(ダーティリードを除く)からすべてを保護できます。
単一のロックはオブジェクトにまたがることができないため、単一のロックになることはできません。しかし、NOLOCKを使用したクエリがない限り、これで目的を達成できると私は信じています(そうすると、要求したとおりの結果が得られます!)。
BEGIN TRANSACTION;
SELECT pkcol FROM dbo.foo WITH (UPDLOCK, HOLDLOCK)
UNION ALL
SELECT pkcol FROM dbo.bar WITH (UPDLOCK, HOLDLOCK);
-- do other stuff
UPDATE dbo.foo SET ...;
UPDATE dbo.bar SET ...;
-- do other stuff
-- default isolation level users will be blocked until:
COMMIT TRANSACTION;
NOLOCKを使用すると、ユーザーが途中で侵入して2つのテーブルからクエリを実行し、更新後の最初のテーブルと更新前の2番目のテーブルからデータを取得する可能性があります。しかし、繰り返しになりますが、NOLOCKを許可するとそれが得られます。
また、ある時点で、デフォルトの分離レベルのユーザーがbar
にクエリを実行してold値を表示できても、foo
でブロックされる可能性があります。
ロックバンドワゴンに渋々とジャンプします。
タイトルが言うように、実際に更新のためにデータベースをロックしたいのであれば、データベースを シングルユーザーモード にして、接続のみが接続できることを確認してくださいまったく更新中:
ALTER DATABASE AdventureWorks2012
SET SINGLE_USER
GO
そして更新後:
ALTER DATABASE whatever
SET MULTI_USER
GO
ただし、これは注意が必要な場合があることに注意してください。たとえば、SSMSは定期的に多くの接続を開くため、これらのモードでは動作が低下します。最善の策は、このモードでsqlcmdを使用することです。