2

Products多くの列で呼び出されるテーブルがあります。これは、レポートの目的で使用される一時的なテーブルです。データは、複数のユーザー要求によって同時にこのテーブルに処理されます。このテーブルに対してDML操作を行うための個別のストアドプロシージャがあります。

テーブル構造:

CREATE TABLE Products (
  instance uniqueidentifier,
  inserted datetime,
  col1, 
  col2,
  ...
)

列には、各行が挿入された時刻を含むinsertedデータが入力され、列にはからの値が含まれます。1つのユーザーリクエストには1つの一意のIDがありますが、100万行になる場合があります。以下は、デッドロックの原因となる、同時に実行されるクエリです。教えてくださいGETDATE()instancenewid()

クエリ1:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
DELETE P 
FROM Products (NOLOCK) 
WHERE instance = 'XXXX-xxx-xxx-xx'

クエリ2:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
DELETE P 
FROM Products (NOLOCK) 
WHERE inserted <= DATEADD(hh, -10, GETDATE())

注:非クラスター化インデックスは、インスタンス列に作成されます。

このシナリオで使用できるロックを教えてください。

テーブルに1,000万行を挿入すると時間がかかるため、主キーを設定できなかったことに注意してください(これは、1つのトランザクションに対して、20の同時トランザクションがあります)。レポートはもっと早く生成する必要があります。そして、私のプロシージャには複数の35のDMLステートメントがあります。インスタンスcolumnと他のcolumns(DELETE FROM table WHERE instance = @instance AND col1 = @col1)には約15のDELETEステートメントがあります。

4

2 に答える 2

6

read uncommitted(1)アイソレーションの使用をやめるべきです。少なくとも を使用してくださいread committed

(2) 異なるトランザクションがデータベース オブジェクトに同じ順序でアクセスするようにするなど、デッドロックを回避するために試行できることがいくつかあります。これは読む価値があります - http://support.microsoft.com/kb/ 169960

(3) テーブルのロック エスカレーションを無効にします (ロックを細かくすると同時実行性が向上しますが、ロック オーバーヘッドが増加します)。

ALTER TABLE Products SET (lock_escalation = disable)

(4) ページ ロックを許可せず、インデックスの行ロックを許可します (つまり、インデックスを最適化することはできませんが、インデックスを再構築することはできます)。

ALTER INDEX [<YourIndex>] ON Product WITH (allow_row_locks = on, allow_page_locks = off)
于 2013-02-25T18:31:52.110 に答える
1

まず、排他ロック以外に、これらの削除ステートメントで使用できるロックはありません。あなたの分離レベルとNOLOCKヒントは Sql Server によって無視されています:

(Nolock)SELECTステートメントにのみ適用されます。

2 つの提案:

非クラスター化インデックスをクラスター化インデックスに変更しますinstance。ただし、に変更できる場合にのみこれをNEWID()行ってくださいNEWSEQUENTIALID()

次に、delete10 時間以上経過したレコードを削除する代わりに、ローリング パーティションの実装を検討してください。これにより、他の操作とのクリーンアップによって引き起こされた競合が解消されますdelete

于 2013-02-25T19:04:14.107 に答える