2014-09-24 30 views
0

我已经在sql中创建了一个排序“队列”,我希望能够将一个项目设置为不可见以半模拟一个天蓝色的队列(而不是在工作人员无法处理它,它会自动出现在队列中供其他工作人员读取)。原子执行存储过程

按照建议从这个SO:Is T-SQL Stored Procedure Execution 'atomic'?

我包的begin tran,并承诺在我spDeQueue程序,但我仍然运行到重复的从我的测试剂拉。 (他们都试图同时空的10队列和我越来越复读,我不应该)

这是我的存储过程

ALTER PROCEDURE [dbo].[spDeQueue] 
    @invisibleDuration int = 30, 
    @priority int = null 
AS 
BEGIN 

    begin tran 
     declare @now datetime = GETDATE() 

     -- get the queue item 
     declare @id int = 
     (
      select top 1 
       [Id] 
      from 
       [Queue] 
      where 
       ([InvisibleUntil] is NULL or [InvisibleUntil] <= @now) 
       and (@priority is NULL or [Priority] = @priority) 
      order by 
       [Priority], 
       [Created] 
     ) 

     -- set the invisible and viewed count 
     update 
      [Queue] 
     set 
      [InvisibleUntil] = DATEADD(second, @invisibleDuration, @now), 
      [Viewed] = [Viewed] + 1 
     where 
      [Id] = @id 

     -- fetch the entire item 
     select 
      * 
     from 
      [Queue] 
     where 
      [Id] = @id 
    commit 

    return 0 
END 

我应该怎么做,以确保此行为atomicly ,以防止重复出队。

感谢

回答

1

您的交易(即间“开始反式”和“承诺”语句)是在这个意义上,要么所有的语句将被提交到数据库,要么都不原子。

看来你有事务与同步/互斥执行混淆。

读入事务隔离级别应该有助于强制执行顺序执行 - 可重复读取可能会有所诀窍。 http://en.wikipedia.org/wiki/Isolation_(database_systems)

+0

这似乎工作,但我收到一些例外,可能死锁。我会调试一下,并进一步弄清楚事情。 – ohmusama 2014-09-24 21:40:50

+0

'无法访问队列:事务(进程ID 60)在锁定资源上与另一个进程死锁并被选为死锁牺牲品。重新运行交易。' 这是正常的吗? – ohmusama 2014-09-24 21:52:05

+0

好吧把它修改为'serializable'(来自'repeatable read'),它现在看起来并没有死锁,谢谢。 – ohmusama 2014-09-24 22:02:55