Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.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 2005_Transactions_Deadlock_Sql Server Agent - Fatal编程技术网

Sql 由事务隔离级别分隔的并发进程上的死锁

Sql 由事务隔离级别分隔的并发进程上的死锁,sql,sql-server-2005,transactions,deadlock,sql-server-agent,Sql,Sql Server 2005,Transactions,Deadlock,Sql Server Agent,我们有一张工作表。服务器代理作业在游标中从该表中获取100个条目并执行一些工作。为了并行化,有10个服务器代理作业,它们调用以下过程(每个过程都有自己的@process\u id): 在这10项代理工作中,我们经常遇到僵局。有人知道为什么会这样吗?为了防止副作用,我们使用序列化事务隔离级别,所以只有一个代理作业可以获取一个workorder条目。如果不设置事务隔离级别,死锁就会消失,但通常会出现两个(或更多)死锁代理作业获取相同的workorder条目。我还没有试图明确说明在您的情况下会发生死锁

我们有一张工作表。服务器代理作业在游标中从该表中获取100个条目并执行一些工作。为了并行化,有10个服务器代理作业,它们调用以下过程(每个过程都有自己的
@process\u id
):


在这10项代理工作中,我们经常遇到僵局。有人知道为什么会这样吗?为了防止副作用,我们使用序列化事务隔离级别,所以只有一个代理作业可以获取一个workorder条目。如果不设置事务隔离级别,死锁就会消失,但通常会出现两个(或更多)死锁代理作业获取相同的workorder条目。

我还没有试图明确说明在您的情况下会发生死锁的原因,但似乎您正在有效地使用表作为队列,在这种情况下,请参阅使用
输出
子句和锁定提示的方法,以最大限度地提高并发性,而不出现死锁。

看到了吗听起来很棒!我将尝试一下(稍后再给出反馈),这似乎完全符合我们的需要,非常棒。请回答你的评论。
CREATE PROCEDURE sp_do_workorder @process_id INT
AS
BEGIN TRY
    DECLARE @wo_id NCHAR(40),
        @wo_action NVARCHAR(100),
        @created_at DATETIME,
        @source_proc_name NVARCHAR(100),

    UPDATE procedure_ctrl SET [status]='running' WHERE [procedure]='sp_do_workorder_'+CAST(@process_id AS NVARCHAR(100)) AND [status]='idle'

    WHILE 1=1
    BEGIN
        IF NOT EXISTS (SELECT * FROM procedure_ctrl WHERE [procedure]='sp_do_workorder_'+CAST(@process_id AS NVARCHAR(100)) AND [status]='running') BREAK

        SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
        BEGIN TRANSACTION
            UPDATE workorder SET hash=CAST(@process_id AS NVARCHAR(100))
            FROM workorder x
            INNER JOIN (
                SELECT TOP 100 id FROM workorder WHERE hash='' AND workorder_step=0 ORDER BY created_at ASC
            ) y ON x.id=y.id
        COMMIT TRANSACTION
        SET TRANSACTION ISOLATION LEVEL READ COMMITTED

        DECLARE wo_cur CURSOR FAST_FORWARD FOR SELECT id,action,created_at,optin_source FROM workorder WHERE hash=CAST(@process_id AS NVARCHAR(100)) AND workorder_step=0 ORDER BY created_at ASC
        OPEN wo_cur
        FETCH NEXT FROM wo_cur INTO @wo_id,@wo_action,@created_at,@source_proc_name
        WHILE @@FETCH_STATUS=0
        BEGIN
            EXEC sp_basisprozess @wo_id,@wo_action,@created_at,@source_proc_name,@process_id
            FETCH NEXT FROM wo_cur INTO @wo_id,@wo_action,@created_at,@source_proc_name
        END
        CLOSE wo_cur
        DEALLOCATE wo_cur

        WAITFOR DELAY '00:00:01'
    END

    UPDATE procedure_ctrl SET [status]='idle' WHERE [procedure]='sp_do_workorder_'+CAST(@process_id AS NVARCHAR(100)) AND [status]='running'
END TRY
BEGIN CATCH
    EXEC dbo.sp_listerror
    DECLARE @error NVARCHAR(4000)
    SET @error='[sp_do_workorder]_'+CAST(@process_id AS NVARCHAR(100))+': critical problem'
    RAISERROR(@error, 12, 1)    
END CATCH