web-dev-qa-db-ja.com

SQLサーバーが特定の更新/削除ステートメントに対して行ロックを使用するように強制する方法

私は同様の質問へのこの素晴らしい応答を読みました 行ロックの使用を強制する方法 が、インデックスに行ロック制限を永続的に置くのではなく、更新/削除ごとのステートメントを探していました。

私の問題は、複数のセッションで同じスクリプトを実行し、同じテーブルを更新していくつかのデッドロックを発生させていることです...そして、異なるセッション間で競合する行が発生することはありません。問題はページロック(ページに2つのセッション間で競合するデータが含まれている場合)が原因のようです。更新および削除ステートメントWITH(ROWLOCK)ヒントを使用しようとしましたが、ロックを分析したとき(トランザクションとステートメントを開始してから確認したとき)別のセッションのsp_lock)、WITH(ROWLOCK)ヒントを指定することと指定しないことの違いはまったくありません。

この問題を解決するためのアイデアは大歓迎です。

詳細のために編集: "With(ROWLOCK)"を使用した場合と使用しない場合のさまざまなシナリオをテストするさまざまなスクリプトを実行しました...テストしたテストシナリオは次のとおりです。

-- deleting 9 rows of 4600 - no difference between with or without rowlock hint
-- 9 row locks and 3 page locks
-- COL1 is part of the combined PK
-- DELETE FROM RPT_CHK WHERE COL1='RPT_LAST' 
-- DELETE FROM RPT_CHK with(rowlock) WHERE COL1='RPT_LAST' 

-- updating 16000 rows - no difference between with or without rowlock hint
-- table lock in both cases (which is understandable)
-- update price with (rowlock) set cost = cost + 0.05
-- update price set cost = cost + 0.05

-- no difference between with or without rowlock hint
-- 3833 rows -- 4028 locks (row and page Locks)
-- update client set COL1 = 'a' where ClientId <= 3833
-- update client with (rowlock) set COL1 = 'a'  where ClientId <= 3833
2
JohnG

(rowlock)であなたが言ったことが機能していないようでした
セットに<>を含めていますか。更新ロックが回避されるためです。

update table with (rowlock) 
set col1 = 1 
where col1 <> 1

(tablock holdlock)を使用すると、デッドロックが修正される場合があります
そのため、一度に1つのアップデートしかありません
試してみる価値があります

トランザクションは同じ順序でテーブルを更新していますか?

2
paparazzo

MSDN Table Hints トピックの一部のメモは、ROWLOCKヒントが機能する方法と機能しない方法の制限を示しています。これは[〜#〜]ヒント[〜#〜]であることを覚えておいてください[〜#〜]要件[〜#〜]

予想と一致しない可能性がある問題の例:

行レベルのロックを取得するロックヒントROWLOCK、UPDLOCK、およびXLOCKは、実際のデータ行ではなく、インデックスキーにロックを設定する場合があります。たとえば、テーブルに非クラスター化インデックスがあり、ロックヒントを使用するSELECTステートメントがカバリングインデックスによって処理される場合、ロックは、ベーステーブルのデータ行ではなく、カバリングインデックスのインデックスキーで取得されます。

また、可能性は低いですが、次の問題があります。

クエリプランでテーブルにアクセスしない場合、テーブルヒントは無視されます。これは、オプティマイザがテーブルにまったくアクセスしないことを選択したか、代わりにインデックス付きビューにアクセスしたことが原因である可能性があります。後者の場合、インデックス付きビューへのアクセスは、OPTION(EXPAND VIEWS)クエリヒントを使用して防ぐことができます。

ヒントの状態に影響を与える他の相互作用がある可能性があります。

2
RLF