Sql Server事务/隔离级别和锁定

时间:2012-06-27 15:15:35

标签: transactions sql-server-2008-r2

我有一个更新10个表的SQL Server存储过程,另一个只更新这10个表中的一个表。我们分别称它们为sp_updateAll和sp_updateSingle。 比如说,sp_updateAll的伪代码是:

Create Stored Procedure sp_updateAll
Begin
    Begin TRAN
        UPDATE TABLE1 
        SET COLUMN = ‘VALUE’

        UPDATE TABLE2 
        SET COLUMN = ‘VALUE’
        …
        UPDATE TABLE6 
        SET COLUMN = ‘VALUE’
        …
        UPDATE TABLE10 
        SET COLUMN = ‘VALUE’
  COMMIT TRAN
End 

sp_UpdateSingle的伪代码是:
//这会更新Table6,例如,实际上它可以是10个表中的任何一个

Create Stored Procedure sp_updateSingle
Begin
    Begin TRAN
    IF sp_UpdateAll is in progress, return an error.
    UPDATE TABLE6 
    SET COLUMN = ‘VALUE’
    COMMIT TRAN
END

我想确保一旦sp_updateAll开始执行,sp_updateSingle应该返回错误。换句话说,在执行sp_UpdateAll时,不应允许对各个表进行更新。 有没有办法使用隔离级别/锁定提示实现此目的?即使我们将隔离级别设置为Serializable,sp_UpdateSingle也可能与sp_UpdateAll一起执行。对于例如如果两个事务同时运行,则可能发生以下情况:

  1. Tran1开始执行sp_UpdateAll。 Tran2开始执行sp_UpdateSingle。
  2. 在达到UPDATE TABLE6之前切换Tran1。所以TABLE6没有被Tran1锁定。
  3. Tran2执行并提交。
  4. Tran1继续执行
  5. 这可能吗?如果是这样,那么避免这种情况的好方法是什么?我们是否需要另外一个表来保持Tran1已经开始执行(类似于InUse指标)?那么这个表应该是第一个在sp_UpdateAll中更新的表;我们设置指标并在sp_UpdateAll完成时清除它。 sp_UpdateSIngle在执行更新之前检查此指示符。 请帮助在这种情况下采用什么方法。

    谢谢和问候 维卡斯

1 个答案:

答案 0 :(得分:0)

如果我正确理解这一点,我认为事务隔离级别不是解决方案。

“我想确保一旦sp_updateAll开始执行,sp_updateSingle应该返回一个错误。换句话说,在执行sp_UpdateAll时不应允许对单个表进行更新。”

  • 我认为您可以在第一个事务开始时创建一个## sp1Executing这样的全局临时(虚拟)表,并在事务完成时删除该临时表。
  • 然后在第二个事务中,可以检查表是否在while循环中存在(可能会有延迟),并仅在此表不存在时运行事务。