2011-08-08 14 views
3

以下に示すように、私は、複数のユーザシステムおよびストアドプロシージャでの並列性を持っている:TSQL:ストアドプロシージャとROWLOCK

CREATE PROCEDURE dbo.GetWorkitemID 
AS 
DECLARE @workitem int; 

UPDATE workqueue 
SET status = 'InProcess', @workitem = workitemid 
WHERE workitemid = (SELECT TOP 1 workitemid 
FROM workqueue WITH (ROWLOCK,UPDLOCK,READPAST) 
WHERE status = 'New' ORDER BY workitemid) 

SELECT @workitem 

GO 

それはインプロセス」に「新規」からのシングルレコードステータスを更新し、レコードのを返します。 ID。

質問は次のとおりです:トランザクションスコープでこのストアドプロシージャを使用してROWLOCK、UPDLOCKなどを有効にする必要がありますか?それは必要ですか?そして、第2の:それは本当にスレッドセーフであり、一意性を保証しますか?

答えて

2
  • これは、「キューとして表」を実行するための正しい方法です
    はこれをしてください参照してください。SQL Server Process Queue Race Condition

  • あなたはこのスレッドと並行性の両方のトランザクションに

  • を必要としません。安全

編集:

カバーインデックス UPDLOCKの使用は同じクエリ

DROP table locktest 
create table locktest (id int, workitem int, status varchar(50)) 
insert into locktest (id, workitem) values (1, 1), (2,2), (3,3) 
create index ix_test2 on locktest(workitem) INCLUDE (id, status) 

--When I run this on one connection 
begin tran 
select top (1) id, status 
from locktest with (rowlock, updlock, readpast) 
ORDER BY workitem 

をXLOCKないフィリップ・デ・ヴォスの

ノートへの反例として...私は別の接続で期待される結果を得ます同じクエリで

+0

元のリンクからの回答? – johnny

+0

@Johnny:はい、他の質問に基づいて追加しました – gbn

1

信頼できません。あなたが与えたロックヒントはちょうどロックヒントであるからです。また、表の索引付け方法によっては結果が大きく異なる場合があります。例えば

create table test (id int, workitem int, status varchar(50)) 
insert into test (id, workitem) values (1, 1), (2,2), (3,3) 
create index ix_test on test(workitem) 

私は1つの接続

begin tran 
select * from test with (rowlock, xlock, holdlock) where workitem = 1 

でこれを実行し、私は2番目の接続でこれを実行します。

select top (1) * from test with (rowlock, readpast) order by workitem 

これが返されます。

workitem 
-------- 
3 

同じIがしなければ:

update top (1) test with (rowlock, readpast) 
set status = 'Proc' 
output inserted.workitem 

だから、あなたはあなたが必要なものをピックアップし、同時にこれを使用することができますが、これはインオーダー並行処理を持っている信頼性の高い方法ではありません。

2

私はトランザクションスコープにこのストアドプロシージャを使用する必要があります...

SQLのすべてのDML文では、明示的に開くかどうか、トランザクションのコンテキストで実行されます。既定では、各ステートメントを実行すると、SQL Serverはトランザクションが開かれていない場合はトランザクションを開き、ステートメントを実行してトランザクションをコミットします(エラーが発生していない場合)。

@Filip(ただし、項目が選択される順番は保証されていません)は、安全であり、使用可能でロックされていない場合は、それぞれの呼び出しが異なる行を返します。

関連する問題