2011-01-06 20 views
0

マルチテナントアプリケーションでは、TenantIdカラムのテーブルがあります。このテーブルは、CONTEXT_INFOに格納されたTenantIdを使用して、単一のテナントに属する行を選択するビューを使用してのみアクセスされます。このビューが特定のテナント(つまり、同じTenantIdを持つ行のみをロックする)に対して返すトランザクションのみをトランザクションに持たせる方法はありますか?SQLトランザクションは指定されたビューからのみローをロックできます

挿入/更新/削除されるデータがTenantId列に異なる値を持つデータと決して衝突しないと確信したら、テーブル全体をロックするとパフォーマンスが低下します。

WHERE節を使用していくつかのテーブル行を制限する他のビューにも同じパターンが適用されます。

+1

なぜ、行をロックしたいのですか? – gbn

+0

すべてのテナントにそれぞれ1つではなく共有テーブルがある理由はありますか?とにかくビューを使用している場合、単一の共有テーブルを持つ理由は何ですか? – JNK

+0

申し訳ありません、もっと説明する: すべてのロックは、トランザクション内でない限り、ビューの期間中のみ保持されます。しかし、選択は通常トランザクション内にはありません... – gbn

答えて

4

マルチテナント型の展開でTenantIdカラムクラスタ化インデックスを含むすべての単一のインデックス、における左端の列でなければなりません。結論は、マルチテナントアプリケーションではヒープを持つことができないということです。

のクエリがの場合は、[email protected]という述語を追加する必要があるため、すべてのテーブルのテナントデータスライスの外側にクエリが追加されることはありません。これにより、2人のテナントの間に競合がないことが保証されます。なぜなら、各テナントはインデックスの部分だけに関心があるからです。

TenantIdでパーティション化を使用すると、何とか同様の解決策を達成できますが、パーティション化テーブルに固有の現在の1000パーティション制限とパフォーマンスの低下を考えれば、インデックスキーソリューションを強く推奨します。

ロックエスカレーション(明示的にはALTER TABLE SET LOCK_ESCALATIONで無効にすることができます)やバルクロードテーブルロック(sp_tabeloptionで無効)のような「状態」を破損するものがあります。

この知識で、あなたの質問を再訪し、「テナントが別のテナントが所有するリソースを決してロックできないように孤立化することはできますか?その答えは、適切なテナント固有のアクセスパスがの行セットにあることを確認する限り、はいです。これは、私が最初の段落で言うことを正確に変換します。すべてのインデックスに一番左のキーとして追加します。すべてのクラスタ化されたものを含み、ヒープはありません。小規模な印刷物であればその解決策はほとんどの場合有効ですが、テナントが別のテナントが所有するリソースをロックできる特定のシナリオが常に存在します。しかし、より良いアイソレーションを得るには、テナントごとに1つのdbを用意する必要があります。これは展開/保守/アップグレードの悪夢です。

+0

深い洞察をいただきありがとうございます。私には1つの問題があります。テナントIDは、必ずしも必要ではなかったので、私のクラスタ化インデックスの一部ではありません。主キーは主に1列で構成されているため、製品の場合はProductId BIGINT IDENTITYになります。 ProductIdが行を識別するにもかかわらず、TenantIdを主キーに含めることをお勧めしますか?私のドメインモデルはビュー上に構築されています(例:http://blogs.imeta.co.uk/jyoung/archive/2010/03/22/845)。aspx)、ビューでは、アプリケーションによって使用されるビューがTenantId列を認識しないため、PKは単一の列になります。あなたのソリューションはまだ動作しますか? –

+0

もう1つのことは確かです。このルールは、共通のシステムデータを含むテーブルには当てはまりません。彼らはTenantId列を持っていません。あれは正しいですか? –

+1

クラスタ化されたキーと主キーは2つの異なるものです。あなたのPKを 'ProductId'とすることもできますが、クラスタ化キーは'(TenantId、ProductId) 'でなければなりません。 '@ currentTenantId'は常に指定されるべきです。 'CONTEXT_INFO'を通すとほとんどのシナリオでうまくいきますが、WHERE節以上のものが必要です。すべてのJOINは 'a.TenantID = b.TenantID AND aItItId = b.PArentId'でなければなりません。そして、あなたの外部キーはすべて、 '外部キー(TenantId、ParentId)REFERENCES Parent(TenantId、ItemId)'として宣言されなければなりません。マルチテナンシーを追加すると、設計のあらゆるレベルに浸透します。 –

関連する問題