UPDLOCK、HOLDLOCKについて混乱している


89

テーブルヒントの使用法を調査しているときに、次の2つの質問に遭遇しました。

両方の質問への回答は、を使用すると(UPDLOCK, HOLDLOCK)、他のプロセスがそのテーブルのデータを読み取ることができないと言っていますが、私はこれを見ませんでした。テストするために、テーブルを作成し、2つのSSMSウィンドウを起動しました。最初のウィンドウから、さまざまなテーブルヒントを使用してテーブルから選択したトランザクションを実行しました。トランザクションの実行中に、2番目のウィンドウからさまざまなステートメントを実行して、どれがブロックされるかを確認しました。

テストテーブル:

CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

SSMSウィンドウ1から:

BEGIN TRANSACTION

SELECT * FROM dbo.Test WITH (UPDLOCK, HOLDLOCK)
WAITFOR DELAY '00:00:10'

COMMIT TRANSACTION

SSMSウィンドウ2から(次のいずれかを実行):

SELECT * FROM dbo.Test
INSERT dbo.Test(Value) VALUES ('bar')
UPDATE dbo.Test SET Value = 'baz' WHERE Value = 'bar'
DELETE dbo.Test WHERE Value= 'baz'

ウィンドウ2で実行されるステートメントに対するさまざまなテーブルヒントの影響。

           (UPDLOCK)       (HOLDLOCK)    (UPDLOCK, HOLDLOCK)    (TABLOCKX)
---------------------------------------------------------------------------
SELECT    not blocked      not blocked       not blocked         blocked
INSERT    not blocked        blocked           blocked           blocked
UPDATE      blocked          blocked           blocked           blocked
DELETE      blocked          blocked           blocked           blocked

これらの質問の答えを誤解したり、テストを間違えたりしましたか?ない場合は、なぜあなたは使用する(UPDLOCK, HOLDLOCK)(HOLDLOCK)一人で?


私が達成しようとしていることのさらなる説明:

テーブルから行を選択し、処理中にそのテーブルのデータが変更されないようにしたいのですが。私はそのデータを変更しておらず、読み取りが発生することを許可したいと思います。

この答えは、それ(UPDLOCK, HOLDLOCK)が読み取りをブロックすることを明確に示しています(私が望むものではありません)。この回答に対するコメントは、それがHOLDLOCK読み取りを妨げることを意味します。表のヒントの効果をよりよく理解し、UPDLOCK単独で私が望むことを実行できるかどうかを確認するために、上記の実験を行い、それらの答えと矛盾する結果を得ました。

(HOLDLOCK)はそれを使うべきだと思いますが、間違えたり、見落としたりして、また噛み付くのではないかと心配しているので、この質問です。

回答:


102

UPDLOCKブロックが選択するのはなぜですか?ロックの互換性マトリックスを明らかに示しているNのようにS / UとU / Sの競合のために、競合

HOLDLOCKヒントについては、ドキュメントに次のように記載されています。

HOLDLOCK:SERIALIZABLEと同等です。詳細については、このトピックで後述する「SERIALIZABLE」を参照してください。

..。

SERIALIZABLE:...スキャンは、SERIALIZABLE分離レベルで実行されているトランザクションと同じセマンティクスで実行されます。

そして、トランザクション分離レベルのトピックは何SERIALIZABLE手段について説明します。

現在のトランザクションが完了するまで、他のトランザクションは現在のトランザクションによって読み取られたデータを変更できません。

他のトランザクションは、現在のトランザクションが完了するまで、現在のトランザクションのステートメントによって読み取られるキーの範囲内にあるキー値を持つ新しい行を挿入できません。

したがって、表示される動作は、製品ドキュメントによって完全に説明されています。

  • UPDLOCKは、同時SELECTまたはINSERTをブロックしませんが、T1によって選択された行のUPDATEまたはDELETEをブロックします。
  • HOLDLOCKはSERALIZABLEを意味し、従ってSELECTSを可能にするが、ブロックUPDATEおよび削除T1によって選択された行の、ならびにとして(したがって、テーブル全体でT1により選択された範囲内の任意のINSERT任意の挿入)。
  • (UPDLOCK、HOLDLOCK):実験では、上記の場合に加えて何がブロックされるか、つまりT2でのUPDLOCKを使用した別のトランザクションは示されていません。
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX説明は不要

本当の問題は、何を達成しようとしているのかということです。ロックのセマンティクスを完全に完全に理解せずにロックのヒントを試してみると、問題が発生します...

OP編集後:

テーブルから行を選択し、処理中にそのテーブルのデータが変更されないようにしたいのですが。

より高いトランザクション分離レベルの1つを使用する必要があります。REPEATABLE READは、読み取ったデータが変更されないようにします。SERIALIZABLEは、読み取ったデータが変更されたり、新しいデータが挿入されたりするのを防ぎます。クエリヒントを使用するのではなく、トランザクション分離レベルを使用するのが正しいアプローチです。Kendra Littleには、分離レベルを説明する素敵なポスターあります


+1、そして詳細な回答ありがとうございます。質問を更新して、私の目標の詳細を追加します。
ジェフ緒方

1
@Remus Rusanuは、クエリヒントを使用するのではなく、分離レベルを使用するのが正しいアプローチである理由を詳しく説明していただけますか?2つのテーブルが変更されないようにロックするだけでよく、TABLOCK、HOLDLOCKを使用している手順がありますが、トランザクションで本当に分離レベルに変更してすべてのテーブルをロックする必要がありますか?
スティーブ

TABLOCKXの説明をお願いします:)
niico 2017

注:Kendra Littleのブログエントリへのリンクは404を返します。リンクが示すように、2011年2月2日付けのエントリは見つかりません。
ベーコンビット

22

UPDLOCKは、将来の更新ステートメントのselectステートメント中に1つまたは複数の行をロックする場合に使用されます。将来の更新は、トランザクションの次のステートメントになる可能性があります。

他のセッションは引き続きデータを表示できます。UPDLOCKやHOLDLOCKと互換性のないロックを取得することはできません。

ロックした行が他のセッションで変更されないようにする場合は、UPDLOCKを使用します。ロックされた行を更新または削除する機能が制限されます。

他のセッションが表示しているデータを変更しないようにする場合は、HOLDLOCKを使用します。ロックした行を挿入、更新、または削除する機能が制限されます。これにより、クエリを再度実行して同じ結果を確認できます。


1
ありがとう、しかし私はあなたが私の質問に本当に答えたとは思わない:それらの質問への答えは(UPDLOCK,HOLDLOCK)ブロックが読むと述べることで間違っていた、そして(UPDLOCK,HOLDLOCK)ただの代わりに使う理由があるの(HOLDLOCK)か?
ジェフ緒方

私の2番目のステートメントはあなたの質問に答えます、彼らは間違っています。他のセッションは引き続きデータを読み取ることができます。
スコットブランズ2011年

アップドロック、ホールドロックはホールドロックと同じではありません。Updlock、holdlockは、更新のために行をロックし、トランザクションをシリアル化します。Holdlock自体は、トランザクションをシリアル化するだけです。選択した行をロックして、さらにアクセスすることはできません。
スコットブランズ2011年

「UPDLOCKは、将来の更新ステートメントのselectステートメント中に1つまたは複数の行をロックする場合に使用されます。」XLOCKがいつか機能しない可能性があるので、私はこれが大好きです
Yiping
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.