首页 > 解决方案 > 防止同时执行存储过程

问题描述

我有一个存储过程,它将记录插入到具有顺序令牌编号的表中。我有另一个存储过程,它也将记录插入到同一个表中。

我将从 Web 应用程序的不同用户执行这些存储过程。

例如,我的 Web 应用程序中有一个名为 AddUser 的页面,OfficerA 和 OfficeB 可以访问该页面。这两位官员可以同时按下将同时执行我的存储过程的添加按钮。如果这样做,2 个新用户将获得相同的令牌编号,这不应该发生。

我想创建一个锁定机制,如果一名官员执行该程序,其他官员执行应该等待到第一个完成。

我尝试了以下方法。但不确定它对于等待过程是否足够

create procedure TokenInsertProc(<params here>)
as
begin
DECLARE @returnCode INT

 BEGIN TRANSACTION;
    BEGIN TRY
      EXEC @returnCode = sp_getapplock
            @Resource = 'TokenInsertProc',
            @LockMode = 'Exclusive',
           @LockOwner = 'Transaction',
           @LockTimeout = 50,
           @DbPrincipal  = 'public'

    IF @returnCode NOT IN (0, 1)
    BEGIN
        RAISERROR ( 'Unable to acquire exclusive Lock on TokenInsertProc', 16, 1 )       
        RETURN
    END

-- my procedure insert script goes here 

 EXEC @returnCode = sp_releaseapplock
                        @Resource = 'TokenInsertProc',                       
                        @LockOwner = 'Transaction',
                        @DbPrincipal  = 'public'

 COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
    IF @returnCode IN (0, 1)
        BEGIN
             EXEC @returnCode = sp_releaseapplock
                     @Resource = 'TokenInsertProc',                       
                        @LockOwner = 'Transaction',
                        @DbPrincipal  = 'public'
        END    

        DECLARE @ErrMsg VARCHAR(4000)
        SELECT @ErrMsg = ERROR_MESSAGE()       
        RAISERROR(@ErrMsg, 15, 50)   

        ROLLBACK TRANSACTION;
    END CATCH;
end

或者只是
set transaction isolation level serializable 会有所帮助?

create procedure TokenInsertProc(<params here>)
as
begin
DECLARE @returnCode INT
 set transaction isolation level serializable
 BEGIN TRANSACTION;
    BEGIN TRY

-- my procedure insert script goes here 


 COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH

        ROLLBACK TRANSACTION;
    END CATCH;
end

任何帮助都感激不尽。

编辑 1

为了更清楚,让我发布表格结构

TQHId         TokenNo   TokenStatus TokenSequence
1               A1      Pending     1
6               A2      Pending     2
7               B1      Pending     1
9               I3      Hold        3
10              I4      Pending     4

在这张表中

[TQHId] [int] IDENTITY(1,1) NOT NULL, CONSTRAINT [PK_TokenQHeader] PRIMARY KEY CLUSTERED 
(
    [TokenQHeaderId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

是与 tokenno 没有任何关系的身份字段。我用它作为主键字段。我的令牌编号是使用TokenInsertProc过程中的自定义代码生成的。

正如我提到的,我的问题是这个存储过程可能会同时被两个不同的网络用户调用。我想避免将相同的令牌编号(仅在执行过程时)提供给 2 个不同的用户。

标签: sqlsql-servertsqltransactionslocking

解决方案


推荐阅读