You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server触发器中两种更新逻辑的性能与死锁风险对比

触发器两种更新方式的性能与死锁风险对比

场景说明

表结构

  • Table1结构:
ProductId int(primary key), CurrentStatus, CurrentStatusDate
  • Table2结构:
NewProductId, NewStatus, NewStatusDate

在Table2的插入触发器中,从inserted表获取@NewProductId、@NewStatus、@NewStatusDate,有两种更新Table1的处理方式:

方式1

SELECT @CurrentStatusDate = CurrentStatusDate
FROM Table1
WHERE ProductId = @NewProductId

IF @NewStatusDate >= @CurrentStatusDate
BEGIN
    UPDATE Table1 SET
        CurrentStatus = @NewStatus
        , CurrentStatusDate = @NewStatusDate
    WHERE ProductId = @NewProductId
END

方式2

UPDATE Table1 SET
  CurrentStatus = @NewStatus
  , CurrentStatusDate = @NewStatusDate
WHERE ProductId = @NewProductId
AND CurrentStatusDate <= @NewStatusDate

已知触发器每日运行数万至数十万次,其中90%的场景下NewStatusDate晚于Table1的CurrentStatusDate,需要执行更新。

性能对比

方式1需要对Table1的主键执行两次查找:先SELECT获取当前状态日期,再在满足条件时执行UPDATE。由于90%的场景都要执行UPDATE,等于绝大多数请求都要做两次重复的主键IO操作。

方式2将判断条件直接整合到UPDATE的WHERE子句中,只需要一次主键查找操作,无论是否满足更新条件,都只触发一次IO。这种情况下,方式2的性能大幅更优,能减少大量重复的磁盘IO和锁资源消耗。

死锁风险对比

方式1的操作分为两步:SELECT加共享锁(默认隔离级别下读取后立即释放),之后再尝试加排他锁执行UPDATE。这中间存在时间窗口,若其他事务同时操作同一个ProductId,可能出现事务A等待事务B释放锁、事务B等待事务A释放锁的死锁场景。

方式2是原子性的UPDATE操作,直接在查找时判断条件并完成更新,锁的持有时间极短,没有中间的时间窗口,死锁风险大幅降低。

结论

方式2在性能和死锁风险方面均大幅更优,非常适合当前高触发频率、高更新占比的场景。

内容的提问来源于stack exchange,提问作者V00D00

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:26:04