4

いくつかの非常に小さなテーブルに対して100(!)を超える更新を行うストアドプロシージャのパフォーマンスが非常に低くなり、すべての同時ユーザーが常に相互にブロックしているように見えます。

procの完全な書き直しは今年後半に予定されていますが、それまでの間、影響を受ける各テーブルに行レベルのロックを強制することで問題を軽減できるかどうかを確認したいと思いました。

Sybaseでは、次のステートメントを使用して、テーブルの行レベルのロックを強制できます(または少なくとも2007年頃になる可能性があります)。

alter table titles lock datarows

SQL Serverでは、同じ効果を得る唯一の方法は、すべての更新または挿入ステートメントでWITH(ROWLOCK)を使用することであるように見えます。それでも、無視できるのはヒントにすぎません。

SQL Serverには、特定のテーブルに対するすべての更新に対して行レベルのロックを強制する(または強く支持する)方法はありますか?

4

3 に答える 3

10

何よりもまず、更新がテーブルスキャンではないことを確認してください。言い換えれば、適切なインデックスがあります(UPDATEにもインデックスが必要です...)。慎重に検討した上で、使用するインデックスのページロックを無効にすることを確認した後:

ALTER INDEX ... WITH (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON);

この操作には、TNTのバレルとナパームのボトルをジョグリングする場合と同じ注意を払ってください...


追加情報(以下のコメントから):

  • クラスタ化インデックスでページロックを無効にすることはできますが、ヒープでページロックを無効にすることはできません(物理的に構造化されており、ページをロックしないと適切なロック階層を実行できないため)。

  • ロックのエスカレーションは(関連しているが)別の問題です。ロックのエスカレーションは、ステートメントが行レベルのロックの粒度を選択し、実行中に行セットの粒度レベルにエスカレートすることを決定した場合にのみ発生します。OPが実際にエスカレーションの犠牲になっている可能性があることは事実です。私がOPを読んだ方法から、より可能性の高い原因はインデックスの欠如であると思います(つまり、スキャンのために事前に高いロック粒度が選択され、エスカレーションはトリガーされません)。

  • 初期の粒度レベルは、手元のタスクのエンジン推定の結果です。見積もりが多数の行をロックする必要があることを示している場合、多数の行ロックを取得することは通常問題があるため、代わりにページの粒度を選択する場合があります。インデックスがないとスキャンがトリガーされ、通常はページの粒度が選択されます。

  • また、エスカレーションは行/ページから行セット(オブジェクト)の粒度になります。最初に中間ページレベルを通過すると、同時実行の問題が発生するため、「ビッグハンマー」が使用されます。

于 2013-01-28T09:09:18.937 に答える
0
  1. トレース フラグ 1211
  2. インデックスの変更を介してページ レベルのロックを無効にする

これら2つの組み合わせにより、行レベルのロックが提供されます。もちろん、SQLがテーブルロックに直接行くことを決定しない限り:) 1224フラグもありますが、メモリ不足のリクエストを無視しますが、1211はしません。メモリ消費量が大幅に増加する可能性があり、警告が表示され、ユーザー アクティビティ シミュレーション (RML または Benchmark Factory) を実行し、perfmon を実行して観察します。私は過去にそれをした人を知っています。

于 2014-09-23T17:34:17.173 に答える
0

これを使用して、ロックのエスカレーションを無効にすることができます。

ALTER TABLE titles SET (LOCK_ESCALATION=DISABLE)

ロックのエスカレーションに関するドキュメントを参照してください。

于 2013-01-28T09:23:24.393 に答える