UPDATE触发器导致死锁

Gul*_*han 0 performance sql-server-2008 sql-server sql-server-2012 performance-tuning

我有一个 After Update 触发器,其中触发器在同一个表中插入一个值以查找持续时间列。我的目标是每当插入 end_time 值时,触发器将找到hh:mm:ss格式的持续时间并插入到持续时间列中。

问题-触发器导致如此多的死锁,从而阻塞了另一个进程。

列数据类型信息..

Start_time datetime, End_time datetime, Duration time(3)

ALTER TRIGGER [dbo].[GET_DURATION] ON [dbo].[INBOUND_CALL_xxx]
AFTER UPDATE AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Begin Transaction

               UPDATE INBOUND_CALL_xxx
               SET DURATION = convert(time(0),(END_TIME- START_TIME))                                                     
               FROM INBOUND_CALL_xxx with (nolock)
Commit;
Run Code Online (Sandbox Code Playgroud)

EzL*_*zLo 10

您缺少对inserted仅包含已更新行的特殊表的引用。当前,您的触发器每次都更新跟踪表的所有行。

ALTER TRIGGER [dbo].[GET_DURATION] ON [dbo].[INBOUND_CALL_xxx]
AFTER UPDATE AS
BEGIN

    IF UPDATE(END_TIME) OR UPDATE(START_TIME)
    BEGIN

               UPDATE C
               SET DURATION = convert(time(0),(I.END_TIME - I.START_TIME))                                                     
               FROM 
                inserted AS I 
                INNER JOIN INBOUND_CALL_xxx AS C ON I.KeyColumn = C.KeyColumn

    END

END
Run Code Online (Sandbox Code Playgroud)

您还可以修改触发器以DURATION仅在更新相关列时才更新(截至本示例)。


另一种选择是使用表达式为 的计算列(可能是持久化的)CONVERT(time(0), END_TIME - START_TIME),因此您不需要触发器来保持值更新。

ALTER TABLE INBOUND_CALL_xxx DROP COLUMN DURATION

ALTER TABLE INBOUND_CALL_xxx ADD DURATION AS CONVERT(TIME(0), END_TIME - START_TIME) -- PERSISTED (if needed)
Run Code Online (Sandbox Code Playgroud)