代码之家  ›  专栏  ›  技术社区  ›  Frank V

防止存储过程同时执行两次

  •  7
  • Frank V  · 技术社区  · 17 年前

    理想情况下,我希望代码是自包含且高效(快速)的。我也不想做类似于创建一个全局临时表来检查它是否存在的事情,因为如果该过程由于某种原因失败,它将始终被视为正在运行。。。

    我已经搜索过了,我想还没有人问过这个问题。如果是,对不起。

    5 回复  |  直到 17 年前
        1
  •  10
  •   Mladen Prajdic    17 年前

    是的,有办法。使用所谓的 SQL Server Application locks .

    编辑:是的,这也适用于 SQL Server 2000 .

        2
  •  5
  •   JP Alioto    17 年前

    你可以用 sp_getapplock sp_releaseapplock 如锁a处的示例所示 Stored Procedure for Single Use Only

    但是,这就是你真正想要做的吗?您是否正在尝试与客户进行交易 high isolation level ? 在应用程序级别处理这种类型的并发可能会更好,因为在一般的高级语言中,对于这类事情有更好的原语。

        3
  •  1
  •   palindrom    17 年前

    锁一张虚拟桌子怎么样?在发生故障时,这不会导致死锁。

        4
  •  0
  •   Paul Rowland    17 年前

    在程序开始时,检查数据块是否已“锁定”,如果未锁定

    在程序结束时,解锁数据块。

    即

    SELECT @IsLocked=IsLocked FROM CheckLockedTable Where spName = 'this_storedProcedure'
    
    IF @IsLocked = 1
        RETURN
    ELSE
        UPDATE CheckLockedTable SET IsLocked = 1 Where spName = 'this_storedProcedure'
    
    .
    .
    .
    
    -- At end of Stored Procedure
        UPDATE CheckLockedTable SET IsLocked = 0 Where spName = 'this_storedProcedure'
    
        5
  •  0
  •   Christopher    7 年前

    回复中共享的一个初始外部链接提供了有用的信息,但就我个人而言,我更喜欢将独立的答案/片段放在堆栈溢出问题页面上。请参阅下面的代码片段,了解我使用了什么并解决了(类似)问题。如果任何人有问题(或调整建议),请插话。

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[MyLockedAndDelayedStoredProcedure]') AND type in (N'P', N'PC'))
    DROP PROCEDURE [GetSessionParticipantAnswersFromEmailAddressAndSessionName]
    GO
    
    CREATE PROCEDURE [MyLockedAndDelayedStoredProcedure]    
      @param1 nvarchar(max) = ''
    AS
    BEGIN
    
    DECLARE @LockedTransactionReturnCode INT
    PRINT 'MyLockedAndDelayedStoredProcedure CALLED at ' + CONVERT(VARCHAR(12),GETDATE(),114);
    BEGIN TRANSACTION
    EXEC @LockedTransactionReturnCode =sp_getapplock @Resource='MyLockedAndDelayedStoredProcedure_LOCK', @LockMode='Exclusive', @LockOwner='Transaction', @LockTimeout = 10000
    PRINT 'MyLockedAndDelayedStoredProcedure STARTED at ' + CONVERT(VARCHAR(12),GETDATE(),114);
    
    -- Do your Stored Procedure Stuff here
    Select @param1;
    
    -- If you don't want/need a delay remove this line    
    WAITFOR DELAY '00:00:3'; -- 3 second delay
    PRINT 'MyLockedAndDelayedStoredProcedure ENDED at ' + CONVERT(VARCHAR(12),GETDATE(),114);
    COMMIT
    
    END
    
    -- https://gist.github.com/cemerson/366358cafc60bc1676f8345fe3626a3f