2

我有一个更新 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 时,不应允许对单个表进行更新。有没有办法使用隔离级别/锁定提示来实现这一点?即使我们将 Isolation Level 设置为 Serializable,sp_UpdateSingle 也有可能与 sp_UpdateAll 一起执行。例如,如果两个事务同时运行,可能会发生以下情况:

  1. Tran1 开始执行 sp_UpdateAll。Tran2 开始执行 sp_UpdateSingle。
  2. Tran1 在到达 UPDATE TABLE6 之前被切换。所以 TABLE6 没有被 Tran1 锁定。
  3. Tran2 执行并提交。
  4. Tran1 继续执行

这可能吗?如果是这样,那么避免这种情况的好方法是什么?我们是否需要一个额外的表来维护 Tran1 已开始执行(类似于 InUse 指标)?那么这个表应该是在 sp_UpdateAll 中被更新的第一个表;我们设置指标并在 sp_UpdateAll 完成时将其清除。sp_UpdateSIngle 在执行更新之前检查此指示符。请帮助您了解在这种情况下哪种方法会更好。

感谢和问候
维卡斯

4

1 回答 1

0

如果我理解正确,我认为事务隔离级别不是这里的答案。

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

  • 我认为您可以在第一个事务开始时创建一个全局临时(虚拟)表,如##sp1Executing,并在事务完成时删除此临时表。
  • 在第二个事务中,您可以检查此表是否存在于一个 while 循环中,可能会有延迟,并且仅当此表不存在时才运行您的事务。
于 2018-08-07T14:02:32.540 回答