Упрощённо имеются две таблицы:
1. CREATE TABLE dbo.Events(
EventNumber INT AUTOINCREMENT
)
2. CREATE TABLE dbo.ProcessedEvents (
LastEventNumber INT NOT NULL
)
В таблицу Events параллельно вставляют данные разные producer'ы.
Параллельно работает consumer' который делает след. запрос и после обработки сохраняет LastEventNumber:
SELECT TOP 1
e.EventNumber as LastEventNumber
FROM
dbo.Events e JOIN dbo.ProcessedEvents pe
ON e.EventNumber > LastEventNumber
ORDER BY
e.EventNumber ASC
Как избежать проблемы в этом сценарии:
A> BEGIN;
B> BEGIN;
A> INSERT INTO dbo.Events() ... -- EventNumber = 1
B> INSERT INTO dbo.Events()... -- EventNumber = 2
B> COMMIT;
Если в этот момент времени произойдёт SELECT (READ COMMITED), то LastEventNumber станет 2
A> COMMIT;
В результате EventNumber = 1 будет пропущен consumer'ом.
Как избежать этой ситуации без lock'ов и сериализации транзакций, при этом гарантируя очерёдность событий?