如何设置隔离级别,以便一旦一个事务完成,插入的数据可用于另一个事务?

时间:2013-01-10 12:19:55

标签: sql sql-server azure-sql-database isolation-level transaction-isolation

我有以下表格(大大简化):

Jobs: JobId, JobState
Data: DataId
JobsData: JobId, DataId

JobsData的想法是,Data中的任何项目都可以与Jobs中的一个或多个项目相关联,Jobs中的每个项目都可以包含一个或多个项目与Data相关联。

现在我有两个交易:

-- TRAN1
BEGIN TRAN
INSERT INTO Data VALUES (NewDataId)
INSERT INTO Jobs VALUES (NewJobId, StateInitial)
INSERT INTO JobsData VALUES (NewDataId, NewJobId)
UPDATE Jobs SET JobState=StateReady WHERE JobId=NewJobId
COMMIT TRAN

-- TRAN2
DECLARE @selectedId;
SELECT TOP (1) @selectedId=JobId FROM Jobs WITH (UPDLOCK, READPAST) WHERE JobState=StateReady
IF @selectedId IS NOT NULL
    SELECT DataId FROM JobsData WHERE JobId = @selectedId

带有锁定提示的代码来自from this answer。其目的是让多个TRAN2实例并行运行,并且永远不会获得相同的JobId

该代码在SQL Server(默认隔离级别READ_COMMITTED)中运行良好,但在SQL Azure中TRAN2有时会错误地工作 - 第一个SELECT产生非空{{1}但是,第二个JobId会产生空结果集。我假设这是因为SQL Azure中的默认隔离级别是SELECT

我想进行最少的更改以解决问题 - 以便READ_COMMITTED_SNAPSHOT在第一个TRAN2中检索null,或者在第二个SELECT中检索正确的结果集。

我将哪些表命中应用于我的哪些SQL语句?

1 个答案:

答案 0 :(得分:0)

对于初学者,如果您想在Azure中使用队列,请使用Azure Queues or Service Bus Queues

如果您坚持在关系上实施队列,请使用Using Tables as Queues中的模式。具体做法是:

  • 不要使用州字段而不是事件队列(“就绪”是作业队列中的记录,事件不是状态在作业上)。
  • 使用DELETE ... WITH OUTPUT ...
  • 出列队列

相信我这个。