小弟近日被老大要求给某张表添加一个update 触发器,添加完成之后大部分情况下是OK的,但是某一个操作总是发生死锁。
目前不清楚这个操作具体情况,但根据业务逻辑大概是这样的:
{
开启事务
...
update TASK_TBL xx
...
(可能还会对TASK_TBL这个表进行update操作)
..
结束事务
}
小弟写的触发器:
CREATE TRIGGER PDOCV_PICKUP_TRG ON avaegp.TASK_TBL
AFTER UPDATE
AS
IF UPDATE(INBOX_USER_ID)
BEGIN
DECLARE @ID VARCHAR(18),@USERID VARCHAR(64);
SELECT @ID=REF_NO FROM INSERTED;
SELECT @USERID=INBOX_USER_ID FROM INSERTED;
IF @USERID IS NOT NULL
UPDATE avapems.APPLICATION_SUB SET HAS_PICKUP = 'Y' WHERE APPLICATION_NO = @ID;
ELSE
UPDATE avapems.APPLICATION_SUB SET HAS_PICKUP = 'N' WHERE APPLICATION_NO = @ID;
END
即在update TASK_TBL之后对APPLICATION_SUB 表进行update
敬请各位大侠伸出援手!
------解决思路----------------------
设计应考虑:
1、此触发器能不能保证每个INBOX_USER_ID有一个REF_NO;
2、每次更新的INBOX_USER_ID是否相同;
此触发器只能应用更新1条的情况。
若是更新多行,@ID只是最后一条记录的ID。
应考虑更新行数为0,1,n的情况,0行则直接返回,n行则采取游标等方式处理。
------解决思路----------------------
你业务中对TASK_TBL的批量更新,要改成游标、都按照REF_NO升序的次序逐个处理。
这样不会因为A会话处理REF_NO的次序是(1,2),B会话处理REF_NO的次序是(2,1),它们各种通过触发器更新了APPLICATION_SUB记录后就死锁了。
如果都按照REF_NO升序的次序来处理,就只会发生等待或超时。
------解决思路----------------------
看代码没什么问题,死锁是由2个进程互锁资源造成的,只提供一个进程的代码无法分析.
建议启用1222跟踪标记,发生死锁时查看SQL日志,有详细的死锁日志以利分析.
dbcc traceon(1222,-1)