SP_GetAppLock为什么不立即返回控件?

发布于 2025-02-13 12:26:18 字数 1035 浏览 0 评论 0原文

当我的应用程序中的两个用户运行以下过程时:

CREATE PROCEDURE [dbo].[CopyForm](@varId as uniqueidentifier)
AS
BEGIN
    DECLARE @returnLock INT
    BEGIN try
        EXEC @returnLock = Sp_getapplock
        @Resource = 'CopyFormLock',
        @LockMode = 'Exclusive',
        @LockOwner = 'Session'
 
        IF @returnLock <> 0
        BEGIN
            RAISERROR (
            'the operation is occupied by another user, wait a few minutes',
            16,1
            )
            RETURN
        END
        
        --do stuff

        EXEC @returnLock = Sp_releaseapplock
        @Resource = 'CopyFormLock',
        @LockOwner = 'Session'
    END try
    BEGIN catch
        IF @returnLock = 0
        BEGIN
            EXEC @returnLock = Sp_releaseapplock
                @Resource = 'CopyFormLock',
                @LockOwner = 'Session'
        END
    END catch
END
GO

第一个锁定该过程的用户执行该过程,然后解锁它。第二个用户等待,仅在第一个用户删除锁之后,第二用户才会出现错误:“操作由另一个用户占用,等待几分钟”。 我不明白为什么第二个用户不会立即输出错误,我必须等待第一个错误。 解释我在哪里犯了一个错误,以及如何立即显示错误?

When two users in my application run the following procedure:

CREATE PROCEDURE [dbo].[CopyForm](@varId as uniqueidentifier)
AS
BEGIN
    DECLARE @returnLock INT
    BEGIN try
        EXEC @returnLock = Sp_getapplock
        @Resource = 'CopyFormLock',
        @LockMode = 'Exclusive',
        @LockOwner = 'Session'
 
        IF @returnLock <> 0
        BEGIN
            RAISERROR (
            'the operation is occupied by another user, wait a few minutes',
            16,1
            )
            RETURN
        END
        
        --do stuff

        EXEC @returnLock = Sp_releaseapplock
        @Resource = 'CopyFormLock',
        @LockOwner = 'Session'
    END try
    BEGIN catch
        IF @returnLock = 0
        BEGIN
            EXEC @returnLock = Sp_releaseapplock
                @Resource = 'CopyFormLock',
                @LockOwner = 'Session'
        END
    END catch
END
GO

The first user who locks the procedure executes it and then unlocks it. The second user waits and only after the first user removes the lock, the second user gets the error "the operation is occupied by another user, wait a few minutes".
I do not understand why the error is not output for the second user immediately, and I have to wait for the first one.
Explain plz where I made a mistake, and how to make the error be displayed immediately?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

巨坚强 2025-02-20 12:26:18

您在这里有许多问题:

  • sp_getapplock的结果始终小于失败中的0。如果等于1,则意味着必须等待。
  • 如果您希望该过程立即纾困,如果锁定锁定,请通过@locktimeout = 0
  • 使用投掷而不是raiserror
CREATE OR ALTER PROCEDURE [dbo].[CopyForm](@varId as uniqueidentifier)
AS

SET NOCOUNT ON;

    DECLARE @returnLock INT
    BEGIN TRY
        EXEC @returnLock = sp_getapplock
        @Resource = 'CopyFormLock',
        @LockMode = 'Exclusive',
        @LockOwner = 'Session',
        @LockTimeout = 0;
 
        IF @returnLock < 0
        BEGIN
            THROW
              50001,
              'the operation is occupied by another user, wait a few minutes',
              1;
        END;
        
        --do stuff

        EXEC @returnLock = sp_releaseapplock
        @Resource = 'CopyFormLock',
        @LockOwner = 'Session';
    END TRY
    BEGIN CATCH
        IF @returnLock = 0
        BEGIN
            EXEC @returnLock = sp_releaseapplock
                @Resource = 'CopyFormLock',
                @LockOwner = 'Session';
        END;
        THROW;
    END CATCH

go

You have a number of issues here:

  • The result of sp_getapplock is always less than 0 in a failure. If it is equal to 1 then it just means it had to wait.
  • If you want the procedure to immediately bail-out if the lock is held then pass @LockTimeout = 0.
  • Use THROW instead of RAISERROR.
CREATE OR ALTER PROCEDURE [dbo].[CopyForm](@varId as uniqueidentifier)
AS

SET NOCOUNT ON;

    DECLARE @returnLock INT
    BEGIN TRY
        EXEC @returnLock = sp_getapplock
        @Resource = 'CopyFormLock',
        @LockMode = 'Exclusive',
        @LockOwner = 'Session',
        @LockTimeout = 0;
 
        IF @returnLock < 0
        BEGIN
            THROW
              50001,
              'the operation is occupied by another user, wait a few minutes',
              1;
        END;
        
        --do stuff

        EXEC @returnLock = sp_releaseapplock
        @Resource = 'CopyFormLock',
        @LockOwner = 'Session';
    END TRY
    BEGIN CATCH
        IF @returnLock = 0
        BEGIN
            EXEC @returnLock = sp_releaseapplock
                @Resource = 'CopyFormLock',
                @LockOwner = 'Session';
        END;
        THROW;
    END CATCH

go
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文