2

編集: SQL Server 2005

5 つの個別のサーバーで実行されている顧客アプリケーションがあります。各アプリケーションは、1 つのスケジューリング テーブルを参照します。どのマシンも、他のマシンと同時に同じレコードにアクセスできないようにしたいと考えています。各サーバーは一度に 1 行しか処理できません。基本的に、アプリケーションは実行可能な次のレコードを選択するだけです。何も選択されていない場合は、単に何もせず、さらに 1 分待ってから再試行します。

[編集: より具体的に言うと、dbo.the_table から行が削除されることはありません。IsProcessing=1 をマークするだけで、他のマシンがそれを取得しないようにします]

私のストアドプロシージャ(SQL Server)は次のとおりです。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

SET @ScheduleId = SELECT TOP 1 ScheduleId FROM dbo.the_table WHERE NextRun <= GETDATE() AND IsEnabled = 1

UPDATE dbo.the_table SET IsProcessing=1 WHERE ScheduleId = @ScheduleId

--Edit: Return this to the program so we can do stuff with the data
SELECT * FROM dbo.the_table WHERE ScheduleId = @ScheduleId

IF @@ERROR = 0
COMMIT TRAN
ELSE
ROLLBACK TRAN

トランザクションの進行中は、トランザクションがブロックしているトランザクションによってコミットされるまで、他のマシンによる SELECT ステートメントがブロックされることを確認したいと思います。(たとえば、マシン A がトランザクションを開始します。B、C、D、または E が SELECT を試行すると、トランザクションがコミットされるまで待機します)。

4

1 に答える 1

4

使用している SQL Server のバージョンは何ですか? SQL2005+の場合、これをすべて1つのステートメントで実行できます

;WITH s AS
(
SELECT TOP 1 * 
FROM dbo.the_table WHERE NextRun <= GETDATE() AND IsEnabled = 1
AND IsProcessing = 0 /*?*/
--ORDER BY ScheduleId  ?
)
UPDATE    s  WITH (ROWLOCK, READPAST)
SET     IsProcessing=1 
OUTPUT INSERTED.*  /*Return row that was updated*/
于 2010-08-04T00:09:56.283 に答える