Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在不取消新调用的情况下锁定存储过程_Sql Server_Sql Server 2012 - Fatal编程技术网

Sql server 如何在不取消新调用的情况下锁定存储过程

Sql server 如何在不取消新调用的情况下锁定存储过程,sql-server,sql-server-2012,Sql Server,Sql Server 2012,我有一个存储过程,它每分钟从作业调用一次,但也可以在作业之外的任何时间调用 如果我在作业调用存储过程的同时调用它,问题就会出现 我需要的是让第二次通话等到第一次通话结束后再开始第二次通话 我遵循这一点使用sp_getapplock 注意:我尝试了sp_getapplock,但它取消了第二个调用 更新: 这是我正在使用的示例 ALTER PROCEDURE TestingLocking AS BEGIN SET NOCOUNT ON; SET TRANSACTION ISOLA

我有一个存储过程,它每分钟从作业调用一次,但也可以在作业之外的任何时间调用

如果我在作业调用存储过程的同时调用它,问题就会出现

我需要的是让第二次通话等到第一次通话结束后再开始第二次通话

我遵循这一点使用sp_getapplock

注意:我尝试了sp_getapplock,但它取消了第二个调用

更新: 这是我正在使用的示例

ALTER PROCEDURE TestingLocking
AS  
BEGIN
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    DECLARE @returnCode INT, @DriverID INT, @OrderID int, @CarTypeID int

    EXEC @returnCode = sp_getapplock
            @Resource = 'TestingLocking',
            @LockMode = 'Exclusive',
            @LockOwner = 'Session',
            @LockTimeout = 5,
            @DbPrincipal  = 'public'

    DECLARE db_cursor CURSOR FOR 
        SELECT top 5 OrderID, CarTypeID FROM Orders

    OPEN db_cursor   
        FETCH NEXT FROM db_cursor INTO @OrderID, @CarTypeID
        WHILE @@FETCH_STATUS = 0 
    BEGIN
        --Update Orders Set DriverID = @DriverID WHERE OrderID = @OrderID
    WAITFOR DELAY '00:00:02';
        --INSERT INTO Logs(OrderID,DriverID) Values(@OrderID,@DriverID)

        FETCH NEXT FROM db_cursor INTO @OrderID, @CarTypeID
    END
    CLOSE db_cursor
    DEALLOCATE db_cursor

    EXEC @returnCode = sp_releaseapplock
                        @Resource = 'TestingLocking',                       
                        @LockOwner = 'Session',
                        @DbPrincipal  = 'public'

END
GO
当我从两个SSM实例执行存储的时,第二个实例会引发一个错误

无法释放应用程序锁(数据库主体:“public”, 资源:“TestingLocking”),因为它当前未被保留


您指定了一个5毫秒的锁超时,因此当锁已经被持有时,尝试获取锁的第二个进程当然会立即失败

如果要无限期等待,请指定
-1
作为锁定超时。或者,指定一个合理的超时值(请记住,参数
@LockTimeout
以毫秒为单位)


其次,您没有在语句
EXEC@returnCode=sp\u getapplock…
之后验证调用
sp\u getapplock
的返回值。如果获取锁失败,则不应释放锁。您应该从存储过程或作业返回。检查以下列表中可能的错误代码:


您需要删除事务隔离级别语句并一次性执行该语句(避免使用游标)

类似这样的情况如何(使用OUTPUT子句输入到logs表中):


您不能在SQL Server中锁定存储过程-您只能在数据库中的基础表上进行锁定。您可以显示一些代码吗?您到底为什么使用游标?很少有理由认为这是必要的或好的,尤其是对于每分钟都在运行的东西。老实说,我怀疑您的问题是storedp roc需要工作。@MahmoudFakhry我无法理解您为什么说必须使用游标而没有其他选择,因为您可以使用带有输出子句的Update。您还使用了READ UNCOMMITTED,这意味着您可以读取脏数据,@MahmoudFakhry您的前5条语句中也没有ORDER BY,您无法保证将返回哪5条记录。感谢您,我将锁定超时更改为-1,并且它按预期工作。(参数@LockTimeout以毫秒为单位)很好的提示。@MahmoudFakhry不客气,请查看✔ 下面是我的回答,以表示您的感谢。请阅读此礼节。事实上,我在游标中做了很多事情,比如调用外部API和日志记录。设置事务级别read UNCOMMITTED使存储过程易于读取(并处理)随后回滚的数据。这使得UPDATE和INSERT语句可能无效。我怀疑您的数据中会出现一些数据不一致的情况。
Value   Result
---------------------------------------------------------------------------------------------------
0       The lock was successfully granted synchronously.
1       The lock was granted successfully after waiting for other incompatible locks to be released.
-1      The lock request timed out.
-2      The lock request was canceled.
-3      The lock request was chosen as a deadlock victim.
-999    Indicates a parameter validation or other call error.
UPDATE ORDERS 
SET DriverId = O2.DriverId
OUTPUT Inserted.OrderId, Inserted.DriverId INTO Logs
FROM (SELECT Top 5 OrderId, CarTypeId, DriverId FROM Orders ORDER BY OrderId ) O2
WHERE Orders.OrderId = O2.OrderId