1

開発者が独自のロックメカニズムを実装した sproc を維持していますが、私には欠陥があるように見えました。

CREATE PROCEDURE Sproc 1
AS

Update X
set flag = lockedforprocessing
where flag = unprocessed

-- Some processing occurs here with enough time to 
-- 1. table X gets inserted new rows with a flag of unprocessed
-- 2. start another instance of this Sproc 1 that executes the above update

Select from X
where flag = lockedforprocessing

-- Now the above statement reads rows that it hadn't put a lock on to start with.

分離レベル SERIALIZABLE のトランザクション内で sproc をラップできることはわかっていますが、これは避けたいと思います。

目標は

  1. この sproc の複数のインスタンスが同時に実行され、レコードの独自の「共有」を処理して最大の同時実行性を達成できること。
  2. sproc の実行は、まだ実行中の前の実行を待機してはなりません

「未処理」の値を持つ新しいレコードが読み取られるのを妨げないため、ここで REPEATABLE READ が役立つとは思いません (間違っている場合は修正してください)。

sp_getlock sproc を発見したところ、バグは解決されますが、私の目標ではない正確性をシリアル化します。

私が見る解決策は、プロシージャの実行ごとに独自の一意の GUID を生成し、それをフラグに割り当てることですが、どういうわけか、SQL Server がすぐに解決できるものをシミュレートしていると考えています。

sproc プロセスを実行するたびに行を「共有」して SERIALIZABLE にする唯一の方法はありますか?

よろしく、トム

4

1 に答える 1

0

X に ID フィールドがあると仮定すると、更新された X の一時テーブルが役立ちます。

CREATE PROCEDURE Sproc 1
AS
-- Temporary table listing all accessed Xs
   declare @flagged table (ID int primary key)
-- Lock and retrieve locked records
   Update X
      set flag = lockedforprocessing
   output Inserted.ID into @flagged
    where flag = unprocessed

-- Processing
   Select from X inner join @flagged f on x.ID = f.ID

-- Clean-up
   update X
      set flag = processed
     from x inner join @flagged f on x.ID = f.ID
于 2012-04-11T13:51:54.480 に答える