仅执行基础UPDATE查询时出现SQL事务死锁问题排查求助
死锁原因定位
你遇到的死锁核心诱因是用作查询条件的RootGUID字段未建立索引,和字段类型是uniqueidentifier完全无关。
当UPDATE语句的WHERE条件没有对应索引时,SQL Server必须执行全表扫描才能找到匹配的目标行,扫描过程中会对扫描过的行依次加锁,而非仅对你逻辑上要更新的单行加锁。两个并发UPDATE事务扫描表的顺序一致、但要锁定的目标行位置不同时,就会出现事务A持有行1的锁等待行2的锁、事务B持有行2的锁等待行1的锁的死锁场景,哪怕两个事务逻辑上更新的是完全不同的行。
解决方案
- 优先给
Roots表的RootGUID字段创建唯一索引,建议直接设为主键或者唯一聚集索引:索引可以让UPDATE语句直接定位到目标行,仅对目标单行加排他锁,从根源上消除全表扫描带来的大范围加锁问题。 - 你当前的存储过程中仅包含单条UPDATE语句,SQL Server默认单条DML语句本身具备原子性,不需要额外手动包裹
BEGIN TRANSACTION和COMMIT TRANSACTION,避免后续迭代时不小心拉长事务持锁时间。 - 若索引优化后仍有零星死锁,可以给UPDATE语句加上行锁提示:
UPDATE Roots WITH (ROWLOCK) SET ... WHERE RootGUID = @RootGUID,强制SQL Server优先使用行级锁。 - 你当前使用的READ_COMMITTED隔离级别符合场景需求,不需要调整隔离级别。
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

