Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.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 在自定义消息传递系统(队列)中尝试锁定记录时出现并发问题_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

Sql 在自定义消息传递系统(队列)中尝试锁定记录时出现并发问题

Sql 在自定义消息传递系统(队列)中尝试锁定记录时出现并发问题,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我们正在构建自己的自定义消息传递系统,并且存在并发问题。规则如下: process EXE控制台应用程序锁定3条记录并返回它们 没有其他正在运行的进程我们有5个正在运行的EXE可以拾取其他进程已经获取的任何记录 这很简单,但我还是很困惑 执行锁定和查看的SQL存储过程摘要: 这背后的想法是,我们保留三条新记录,并在SELECT和UPDATE语句上使用行锁将其状态更改为“进行中”。因此,理论上,这些记录应该为一个进程锁定,以便其他进程无法更新甚至选择它们。有人能告诉我我做错了什么吗 ALTER P

我们正在构建自己的自定义消息传递系统,并且存在并发问题。规则如下:

process EXE控制台应用程序锁定3条记录并返回它们

没有其他正在运行的进程我们有5个正在运行的EXE可以拾取其他进程已经获取的任何记录

这很简单,但我还是很困惑

执行锁定和查看的SQL存储过程摘要:

这背后的想法是,我们保留三条新记录,并在SELECT和UPDATE语句上使用行锁将其状态更改为“进行中”。因此,理论上,这些记录应该为一个进程锁定,以便其他进程无法更新甚至选择它们。有人能告诉我我做错了什么吗

ALTER PROCEDURE [dbo].[LockAndPeek] 
    @Count INT,
    @QueueTypeId INT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @ListofIDs TABLE(ID INT);
    DECLARE @StatusIDInProgress INT

    SELECT @StatusIDInProgress = ID FROM QueueStatuses (NOLOCK)
    WHERE Name = 'In Progress'

    INSERT INTO @ListofIDs
    (ID)
    SELECT TOP (@Count) Q.ID 
    FROM
        Queues Q (ROWLOCK) INNER JOIN
        QueueStatuses QS (ROWLOCK) ON Q.StatusID = QS.ID
    WHERE
        QS.Name IN ('New', 'Errored') AND
        Q.TypeID = @QueueTypeID AND
        Q.AvailableTime IS NOT NULL AND
        Q.AvailableTime <= GETUTCDATE()
    ORDER BY Q.ID

    UPDATE Q WITH (ROWLOCK)
    SET 
        STATUSID = @StatusIDInProgress,
        PROCESSED = GETUTCDATE()
    FROM
        Queues Q (ROWLOCK) INNER JOIN
        QueueStatuses QS (ROWLOCK) ON Q.StatusID = QS.ID INNER JOIN
        @ListofIDs LI ON Q.ID = LI.ID
    WHERE
        QS.Name IN ('New', 'Errored')

    SELECT  Q.ID, 
            Q.AvailableTime,
            Q.NumberOfTries,
            Q.Created,
            Q.Processed,
            Q.ErrorData,
            QT.ID QueueTypeID,
            QT.Name QueueTypeName,
            QS.ID QueueStatusID,
            QS.Name QueueStatusName,
            Q.Message
    FROM 
        Queues Q (NOLOCK) INNER JOIN
        QueueStatuses QS (NOLOCK) ON Q.StatusID = QS.ID INNER JOIN
        QueueTypes QT (NOLOCK) ON Q.TypeId = QT.ID INNER JOIN
        @ListofIDs LI ON Q.ID = LI.ID

END

找到了!向@MaxVernon致敬

基本上是@MaxVernon作为评论发布的内容的变体。我的查询如下所示,比以前简单得多:

ALTER PROCEDURE [dbo].[LockAndPeek] 
    @Count INT,
    @QueueTypeId INT
AS
BEGIN

SET XACT_ABORT ON; -- blow up the whole tran on any errors
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRAN

UPDATE Q
SET 
    StatusID = 2, -- In Progress
    Processed = GETUTCDATE()
OUTPUT Inserted.*
FROM (
    SELECT TOP (@Count) * 
    FROM
        Queues WITH (READPAST, ROWLOCK)
    WHERE
        StatusID = 1 AND -- New 
        TypeID = @QueueTypeID AND
        AvailableTime IS NOT NULL AND
        AvailableTime <= GETUTCDATE()
   ORDER BY ID
) Q;

COMMIT TRAN;

END

那么你是否期待着选择。。。使用NOLOCK语句无法读取行锁定的行?您的问题还不清楚。为什么不使用SQL Server的内置队列机制Service Broker?除了我分配StatusIDInProgress变量的第一个选项外,所有的选择都带有ROWLOCK。。。我真的不在乎锁不锁。。。bAlso最后一个SELECT语句我也不太关心,它只是@ListOfIDs表变量中的SELECT和update Queues表中的update,它们都有ROWLOCK。我觉得您需要自动选择和更新行,这样其他进程就不会选择它们。也许这会有所帮助:ID所在的点一次只更新一个进程。我想你也许能把其中一个答案应用到你的特殊问题上。不完全是100%的直截了当,但可能足以让你走上正确的方向。