更新存储过程中的死锁

Posted

技术标签:

【中文标题】更新存储过程中的死锁【英文标题】:Deadlock in Update Stored Procedure 【发布时间】:2015-11-03 08:50:20 【问题描述】:

我正在处理数据输入面板,一次有 300 多个客户在更新数据表上的数据,我正在使用存储过程执行数据表中的更新,看起来像这样..

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:                <Author,,Name>
-- Create date: <Create Date,,>
-- Description:        <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[Update_Tbl_Client_Bpo_Data]

@Id int,
@CId varchar(50),
@Tbc_No varchar(200),
@Name varchar(200),
@EmailId varchar(200),
@MobileNo varchar(50),
@Gender varchar(50),
@LicenseNo varchar(200),
@GirNo varchar(200),
@PanNo varchar(200),
@H_Address varchar(500),
@H_City varchar(200),
@H_PinNo varchar(200),
@H_county varchar(200),
@H_State varchar(200),
@O_Address varchar(200),
@O_City varchar(200),
@O_PinNo varchar(200),
@LAL varchar(200),
@MRNNo varchar(200),
@AF varchar(200),
@NRI varchar(200),
@CP varchar(200),
@Status varchar(200)

AS
BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        SET NOCOUNT ON;



        update Tbl_Client_Bpo_Data 
set

Tbc_No=@Tbc_No,
Name=@Name,
EmailId=@EmailId,
MobileNo=@MobileNo,
Gender=@Gender,
LicenseNo=@LicenseNo,
GirNo=@GirNo,
PanNo=@PanNo,
H_Address=@H_Address,
H_City=@H_City,
H_PinNo=@H_PinNo,
H_county=@H_county,
H_State=@H_State,
O_Address=@O_Address,
O_City=@O_City,
O_PinNo=@O_PinNo,
LAL=@LAL,
MRNNo=@MRNNo,
AF=@AF,
NRI=@NRI,
CP=@CP,
Status=@Status from  Tbl_Client_Bpo_Data  where Id=@Id and CId=@CId 
END

这个存储过程得到像这样的死锁错误......

transaction was deadlocked on lock resources with another process and has been chosen as the deadlock victim. rerun the transaction.

我创建了一个备份模块来查找错误日志,该日志显示此存储过程出现死锁,而更多客户端也尝试更新数据..

我还加了SET TRANSACTION ISOLATION LEVEL READ COMMITTED

但这对我不起作用.. 有人可以给出解决这种情况的解决方案吗..

或者如果有某种机制保持执行过程直到上一次执行完成

【问题讨论】:

Transaction (Process ID) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction的可能重复 @AishvaryaKarthik 我还添加了ISOLATION LEVEL.. 我也在我的问题中提到了这一点 您的表上是否有要更新的索引? @MikeAinOz 不,先生,我没有更新索引,我只是将它们用作条件变量 您可能应该考虑做a little more investigation using tracing and the deadlock event reporting 以确保到底发生了什么,即是否只是此语句与使用相同语句的其他更新冲突,是它在做其他事情的事务中,持有什么样的锁等等。这种调查非常熟练,很难远程描述,但你可能会在dba上得到一些建议 【参考方案1】:

简答

您的表上可能缺少索引。首先,您必须检查您的更新是否正在生成表扫描,如果是,则在 ID 和 CID 上创建一个索引以查看是否可以解决您的问题。

长答案

你的表上的更新语句可以引入表扫描。这意味着,SQL Server 读取表中的每一行以检查是否需要更新行。在该读取操作期间,SQL Server 在行上发布 (U) 更新锁。如果需要更新行,它会将 (U) 锁转换为 (X) 独占锁并持有该锁直到事务结束。 (U) 锁与其他 (U) 或 (X) 锁不兼容。

在您的情况下,您有 2 个会话在等待对方。每个会话将 X 锁放在(不同的)行上,并尝试发出(U)锁并读取由其他会话更新的行(持有(X)锁)。实际上它有点复杂 - 你涉及超过 2 个会话,但我希望你能有所了解。

创建索引以避免更新期间的表扫描

【讨论】:

非常感谢您的帮助。它可以工作,但有时会出现此错误,我还在我的表中添加了索引,现在它的工作就像魅力一样。谢谢您的帮助,先生

以上是关于更新存储过程中的死锁的主要内容,如果未能解决你的问题,请参考以下文章

mysql 存储过程出现死锁

由于两次会话同时访问相同的存储过程,因此发生了事务(进程ID)死锁

这样的存储过程会导致死锁吗?

mysql之存储过程--批量更新操作

INSERT 和 SELECT SP 之间的死锁

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