事务(进程 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
你说otrecordid
是nvarchar(255)
。为什么@RecordId
nvarchar(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)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。