事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。在 sql server 2014 中

Posted

技术标签:

【中文标题】事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。在 sql server 2014 中【英文标题】:Transaction (Process ID) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. in sql server 2014 【发布时间】:2017-09-05 12:24:58 【问题描述】:

我有一个更新存储过程,我从 c# 代码调用它,我的代码同时在 3 个线程中运行。更新语句通常会抛出错误“事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。重新运行事务”。如何在 sql server 2014 或 c# 代码中解决这个问题?

更新存储过程:

ALTER PROCEDURE sp_UpdateSP
@RecordID nvarchar(50),
@FileNetID nvarchar(50),
@ClassName nvarchar(150) 

 AS

Begin tran t1
UPDATE MYTABLE SET FilenetID=@FileNetID, DOCUMENT_TYPE=@ClassName, CONTROLID='FileAttach' where OTRECORDID=@RecordID 
Commit tran t1

表索引: 非唯一、非聚集 OTRECORDID 升序 nvarchar(255)

谢谢

【问题讨论】:

此过程不会单独导致任何死锁。您是否在线程中的任何其他过程或查询中使用此表? 不要以sp_ 开头您的过程名称。 Is the sp_ prefix still a no-no? - Aaron Bertrand 你说otrecordidnvarchar(255)。为什么@RecordIdnvarchar(50)的参数是? 需要完整的表 DDL,包括索引和执行计划才能真正了解发生了什么。此 UPDATE 是否预计会影响多行?如果不是,为什么 OTRECORDID 上没有唯一索引? 【参考方案1】:

我怀疑问题是由 SQL 对表执行扫描引起的,因为它认为这比在索引上查找然后通过 keylookup 查找要更新的行更快。

您可以使用FORCESEEK 提示阻止这些扫描并强制 SQL 执行查找。

你的代码会变成

Begin tran t1
UPDATE mt SET FilenetID=@FileNetID, DOCUMENT_TYPE=@ClassName, CONTROLID='FileAttach' FROM MYTABLE mt WITH(FORCESEEK) where OTRECORDID=@RecordID 
Commit tran t1

这会比扫描慢,但会降低死锁的概率。

【讨论】:

【参考方案2】:

这可能不是确切的答案,但如果您想要一种解决方法来跳过该问题,请运行服务:

Win + R > 输入 services.msc

找到 SQL Server 服务 - 如果您只有一个实例,通常命名为 SQL Server (MSSQLSERVER) - 然后重新启动服务,现在死锁的事务已经消失,您可以继续工作。

【讨论】:

以上是关于事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。在 sql server 2014 中的主要内容,如果未能解决你的问题,请参考以下文章

由于 2 个会话同时访问相同的存储过程,导致事务(进程 ID)死锁

关于死锁的问题

事务(进程 ID 120)与另一个进程在锁资源上死锁,并已被选为死锁牺牲品。重新运行事务

SqlException 事务(进程 ID 159)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

SqlException 事务(进程 ID 159)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

事务(进程 ID 84)与另一个进程在锁资源上死锁,并已被选为死锁牺牲品