3

ロック後にレコードを更新するために、SQLサーバーのROWLOCKを理解しようとしていました。これが私の観察であり、ROWLOCKがテーブルまたはページロックのようなものであるかどうか、または正しく試していないかどうかを確認したいと思います。ROWLOCK は、テーブルまたはページではなく、行のみに対するロックである必要があります。

これが私が試したものです:

IDNamerow_lock_temp_testの2 つの列を持ち、PK やインデックスを持たない単純なテーブルを作成しました。ここで、2 つの異なるクライアントであるが同じ資格情報である SQL Server を開き、次のように一連のクエリを実行しようとしました。

クライアント 1:

1: BEGIN TRANSACTION;
2: update row_lock_temp_test set name = 'CC' where id = 2
3: COMMIT

クライアント 2:

1: BEGIN TRANSACTION;
2: update row_lock_temp_test set name= 'CC' where id = 2
3: COMMIT

C-1 でクエリ 1、2 を実行し、C-2 に移動して同じクエリを実行しました。両方のクライアントがクエリを実行し、トランザクションをコミットしました。すべて問題ありません。

次に、クエリを更新するために RowLock を追加しました。

C-1

  1: BEGIN TRANSACTION;
  2: update row_lock_temp_test WITH(rowlock) set name = 'CC' where id = 2
  3: COMMIT

C-2

1: BEGIN TRANSACTION;
2: update row_lock_temp_test WITH(rowlock) set name = 'CC' where id = 2
3: COMMIT

ここで、C-1 でクエリ 1 と 2 を実行してから C-2 に移動し、同じ 2 つのクエリを実行しようとしましたが、行が C-1 によってロックされているため、クエリは期待どおりスタックし、それまでキューに入れておく必要があります。トランザクションは C-1 でコミットされます。C-1でトランザクションをコミットするとすぐに、C-2でクエリが実行され、C-2でもトランザクションをコミットしました。すべて良い。

ここでは、行 ID = 3 で同じ一連のクエリを実行する別のシナリオを試しました。

C-2

 1: BEGIN TRANSACTION;
 2: update row_lock_temp_test WITH(rowlock) set name = 'CC' where id = 3
 3: COMMIT

C-1 で最初の 2 つのクエリを実行してから、C-2 の最初の 2 つのクエリを実行しました。両方のクライアントで行 ID が異なりますが、それでも C-2 のクエリがスタックしました。これは、id = 2 でクエリを更新しているときにページまたはテーブルがロックされたことを意味します。行ロックを予期していましたが、ページまたはテーブル ロックのようです。

また、xlock、HOLDLOCK、および UPDLOCK をさまざまな組み合わせで使用してみましたが、常にテーブルをロックしています。行のみをロックする可能性はありますか。

選択と挿入は期待どおりに機能しています。

前もって感謝します。

4

1 に答える 1