SQLシノニムを使用して、コードを複製せずにローカルデータベースとリモートデータベースのテーブルを切り替えるアプリケーションを使用しています。
BEGIN TRANSACTION
if (@isRemote = 1)
BEGIN
CREATE SYNONYM SY_SUBJECTS FOR [MT00011].[DBO].[SUBJECTS];
END
ELSE
BEGIN
CREATE SYNONYM SY_SUBJECTS FOR [SUBJECTS];
END
-- do some complex work on SY_SUBJECTS
DROP SYNONYM SY_SUBJECTS
COMMIT
このコードは、複数のリクエストによって同時に呼び出されます。このコードが同時に呼び出されると問題が発生するのではないかと心配しています。単一のSQLデータベースで99%の時間実行され、「リモート」のケースは数時間後に実行されます。
ここに問題はありますか?
CREATE SYNONYM
がSCH-M
(スキーマ変更)ロックを取得するため、コードはすでにスレッドセーフです。これは、他のユーザーが同じシノニムを作成しようとする試みをブロックし、ロック所有者のトランザクションが完了するまで待機します。
これにより、既存の同義語オブジェクトに関連するエラーも本質的に防止されます。実際、別のスレッドから(NOLOCK
/READ UNCOMMITTED
を使用せずに)同義語の存在を確認しても、ロックが解除されるまでブロックされます。
したがって、この設計では、最初から同時操作を許可することはできません。同時アクセスが必要な場合は、次の方法で設計を変更できます。
ほとんどの場合、ローカルバージョンのシノニムが使用されるため、ローカル定義を使用してデータベースに永続的に作成します。リモートバージョンが必要な場合、コードは(トランザクション内で)リモート定義を使用してシノニムを削除および再作成し、その作業を実行してから、ローカル定義を使用して削除および再作成し、トランザクションが開始されたときの状態に戻すことができます。
これは、リモートの呼び出し元が最初にロックを取得した場合、上記と同じ理由で他の呼び出し元をブロックします。ローカルの呼び出し元がシノニムを使用している場合は、SCH-S
(スキーマ安定性)ロックを取得して保持する可能性があります。これにより、シノニムが削除されなくなり、ロックが保持されている限りリモートの呼び出し元がブロックされます。 。これにより、ローカルの呼び出し元が処理中であり、リモートの呼び出し元が処理を行っている間、途中で待機する可能性があります。
少し予測不可能になるため、私はそれを許可することに少し警戒しています(つまり、プロセスのタイミングメトリックを記録している場合、それは至る所にある可能性があります)。これを解決するには、 sp_getapplock
を使用して、ローカルの呼び出し元にはShared
ロックを、リモートの呼び出し元にはExclusive
ロックを要求します。これにより、同時ローカル呼び出し元が許可され(リモート呼び出し元が実行されている場合は待機します)、リモート呼び出し元は、すべてのローカル呼び出し元が完了するのを待ってから実行されます。
SYNONYM
を作成またはドロップすると、データベースランドスケープの定義が変更されます。したがって、そうしたステップをいつ実行できるかを厳密に制御しない限り、リスクがあると私は考えます。
接続がSYNONYM
をリセットする場合、その接続ではなくServerおよびdatabaseの同義語が変更されます。これは、別のプロセスで実行されている「複雑な作業」のセットが、警告なしにリモートデータ(たとえば)からローカルデータへの切り替えに巻き込まれる可能性があることを意味します。それは片付けるために混乱を残すでしょう。
実行中のシステムでのテーブルの削除と再作成を表示するように、これを表示します。多くの場合、誰にも気付かれずに機能しますが、実際に問題が発生する可能性があります。
もちろん、別の接続がすでに存在するSYNONYM
を定義しようとすると、「データベースに 'SY_SUBJECTS'という名前のオブジェクトがすでに存在します。」などのエラーが発生します。これにより、シノニムが削除されるまで、コンテキストを切り替える必要がなくなります(ただし、エラーに対処する必要があります)。 (明らかにもっと危険な_ALTER SYNONYM
_関数はありません。)
したがって、最初にSYNONYM
を削除せずに変更しようとすると、失敗します。
コードパスが_DROP SYNONYM
_を実行する場合、必要なロックを取得できれば成功します。 MSDNから:「シノニムへの参照はスキーマにバインドされていないため、シノニムはいつでも削除できます。」
そのため、_DROP SYNONYM
_は実行中のトランザクションを停止せず、トランザクションが完了するまで待機します。