执行插入导致死锁的T-SQL触发器

时间:2015-11-25 15:46:02

标签: sql-server triggers deadlock

我有一个名为Agent_Events的SQL表,它记录" jobs"因为我们系统的用户没有报告更好的术语。乔布斯将开始,有些时间晚些时候结束。我们希望保留所有系统作业的记录,因此我们有一个触发器,当从Agent_Events表中删除一行时,获取记录,并在作业结束时将作业记录插入到report_Agent_Events表中,确定到目前为止。这是触发器:

ALTER TRIGGER [dbo].[tAgentEvents]
ON [dbo].[Agent_Events]
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON  
    DECLARE @callUID nvarchar(10)
    SELECT @callUID = [raw_call_ucid] FROM DELETED
    DECLARE @callID bigint
    SELECT TOP 1 @callID = [ID] FROM report_ExtensionCalls WHERE UCID = @callUID ORDER BY [time_finished] DESC

    INSERT INTO [report_agent_Events]
        ([Agent_Name],[time_started],[time_ended],[duration],[clientStatus],[agentStatus],[Call_ID],[Reference_ID])
        (   SELECT
                [Agent_Name],[time_started],GETDATE(),DATEDIFF(s,[time_started],GETDATE()),[clientStatus],[agentStatus],@callID as Call_ID,[Reference_ID]
                    FROM
                DELETED
        )
END

我们最近发现的是,当系统上存在大量活动时,多个作业可能同时结束。发生这种情况时,触发器将失败并出现以下死锁错误:

Procedure tAgentEvents:
Transaction (Process ID) was deadlocked on lock resources with another process and has been chosen as the deadlock victim RSS

看起来触发器中的INSERT语句与并发触发器中相同INSERT语句强加的锁冲突。有什么办法可以避免这个问题吗?在我看来,这似乎是一个非常简单的触发器。

提前致谢。

2 个答案:

答案 0 :(得分:1)

这应该适应原始触发器中的所有业务规则,但没有标量变量。

请注意,这极不可能解决死锁问题。你还需要解决这个问题。

$('#x').css('font-size', change + 'px');

答案 1 :(得分:0)

刚刚更新了触发器,使其一次性工作,删除了多行,并在report_ExtensionCalls中有多个匹配项。

ALTER TRIGGER [dbo].[tAgentEvents]
ON [dbo].[Agent_Events]
AFTER DELETE
AS
BEGIN
    WITH CTE AS (
        SELECT d.Id AS DeletedId
            , rec.[ID]
            , ROW_NUMBER() OVER (PARTITION BY rec.UCID ORDER BY rec.[time_finished] DESC) AS RowN
        FROM DELETED AS d
        JOIN report_ExtensionCalls AS rec ON d.[raw_call_ucid] = rec.UCID
    )
    INSERT INTO [report_agent_Events]
        ([Agent_Name],[time_started],[time_ended],[duration],[clientStatus],[agentStatus],[Call_ID],[Reference_ID])
        (   SELECT
                d.[Agent_Name]
                ,d.[time_started]
                ,GETDATE()
                ,DATEDIFF(s,d.[time_started],GETDATE())
                ,d.[clientStatus]
                ,d.[agentStatus]
                ,a.[ID] as Call_ID
                ,d.[Reference_ID]
                    FROM DELETED AS d
                    LEFT JOIN CTE AS a ON d.Id = a.DeletedId AND a.RowN = 1
        )
END

希望有所帮助