Сериализуемая транзакция, подходящая для этого сценария? - PullRequest
2 голосов
/ 04 августа 2010

edit: SQL Server 2005

У меня есть клиентское приложение, работающее на 5 отдельных серверах.Каждое приложение просматривает одну таблицу планирования.Я хочу быть уверен, что ни одна машина не может получить доступ к той же записи одновременно с любой другой машиной.Каждый сервер способен обрабатывать только 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, они будут ждать, пока транзакция не будет зафиксирована).

1 Ответ

4 голосов
/ 04 августа 2010

На какой версии SQL Server вы работаете?Если SQL2005 +, вы можете сделать все это в одном выражении

;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*/
...