edit: SQL Server 2005
I have a customer application running on 5 separate servers. Each application is looking at a single scheduling table. I want to be sure that no machine can access the same record at the same time as any other machine. Each server is capable of processing 1 row only at a time. Basically, the application just selects the next record available that can be run. If nothing is selected, it simply does nothing and waits another minute and tries again.
[edit: To be more specific, no row is ever de开发者_如何学JAVAleted from dbo.the_table. It simply marks IsProcessing=1 so that other machines will not pick that up]
My stored procedure (SQL Server) is as followed:
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
I want to be certain that the while the transaction is in progress, any SELECT statement by the other machines will be blocked until the transaction is committed by the blocking transaction. (e.g., Machine A starts a transaction -- if B,C,D, or E try and SELECT, they will wait until the transaction is committed).
What version of SQL Server are you on? If SQL2005+ you could do this all in one statement
;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*/
精彩评论