【发布时间】:2021-09-16 09:08:17
【问题描述】:
我有一个存储过程,它可以像这样更新一些表:
CREATE PROCEDURE SP_UpdateSomeTables
@bundleId bigint,
@wfStage tinyint
AS
SET XACT_ABORT ON
SET NOCOUNT ON
BEGIN TRANSACTION
UPDATE
table1
SET
[LastUpdated] = GETDATE(),
[WorkflowStage] = @wfStage
WHERE
[Id] = @bundleId
UPDATE
table2
SET
[LastModified] = GETDATE(),
[WorkflowStage] = @wfStage
WHERE
[ResultBundleId] = @bundleId AND
[IsCancelled] = 0
COMMIT TRANSACTION
GO
我收到以下错误:
事务(进程 ID 69)因锁定而死锁 |与另一个进程通信缓冲区资源,并已被选为死锁牺牲品。重新运行事务。
还有其他 SELECT 查询在同一组表上并行运行。
如何避免死锁?
【问题讨论】:
-
仅供参考,
sp_前缀由 Microsoft 保留,用于 S 特殊 P 程序。它应该不用于用户存储过程名称。使用前缀会带来性能成本,并可能导致您的过程在更新或升级后根本无法工作。这也在documentation 中被警告。 -
死锁的原因和解决方法有很多 - 表扫描或锁升级、跨多个事务的操作顺序等 - 需要更多信息 - 表模式、所涉及表的索引、执行计划、死锁图、使用的隔离级别等
-
@Larnu 感谢您的提醒。我没有意识到这一点。不幸的是,这是一个棕地项目,无法重命名 db 对象...
-
解决死锁的第一步是检查死锁图以确定发生死锁的资源。在寻求帮助时,您需要向我们提供死锁图。
-
通常可以通过查询和索引调优来减少死锁。检查死锁中涉及的查询的执行计划,以确保只触及需要的行。
标签: sql-server tsql deadlock database-deadlocks