繁体   English   中英

单个SQL Server表上的死锁

[英]deadlock on a single SQL Server table

我正在使用SQL Server 2008 Enterprise。 并使用ADO.Net + C#+。Net 3.5 + ASP.Net作为客户端访问数据库。 当我访问SQL Server 2008表时,我总是从我的C#+ ADO.Net代码调用存储过程。

我在表FooTable上有3个操作。 并且多个连接将在序列中同时执行它们,即执行delete,execute insert然后执行select。 每个语句(删除/插入/选择)都是单存储过程中的单独的单个事务。

我的问题是,删除语句是否可能发生死锁? 我的猜测是,如果多个连接在同一个Param1值上运行,是否可能发生死锁?

BTW:对于下面的语句,Param1是表FooTable的列,Param1是另一个表的外键(指另一个表的另一个主键聚簇索引列)。 对于表FooTable,Param1本身没有索引。 FooTable有另一列用作聚簇主键,但不是Param1列。

create PROCEDURE [dbo].[FooProc]    
(  
 @Param1 int 
 ,@Param2 int  
 ,@Param3 int  
)    
AS    

DELETE FooTable WHERE  Param1 = @Param1     

INSERT INTO FooTable    
 (  
 Param1  
 ,Param2  
 ,Param3  
  )    
 VALUES    
 (  
 @Param1  
 ,@Param2  
 ,@Param3  
  )    

DECLARE @ID bigint    
 SET @ID = ISNULL(@@Identity,-1)    
 IF @ID > 0    
 BEGIN    
      SELECT IdentityStr FROM FooTable WHERE ID = @ID 
 END

以下是活动监视器表的外观,

ProcessID System Process Login Database Status Opened transaction Command Application Wait Time Wait Type CPU 
52 No   Foo suspended 0 DELETE .Net SqlClient Data Provider 4882 LCK_M_U 0 
53 No George Foo suspended 2 DELETE .Net SqlClient Data Provider 12332 LCK_M_U 0 
54 No George Foo suspended 2 DELETE .Net SqlClient Data Provider 6505 LCK_M_U 0 
(a lot of rows like the row for process ID 54)  

我会在Param1上添加一个索引到FooTable; 没有它,DELETE正在进行全表扫描,这会产生死锁问题。

编辑

根据您的活动详细信息,它看起来不像您有死锁,您有阻塞,许多删除正在排队,同时发生一次删除。 同样,对Param1进行索引可以缓解这种情况,如果没有它,每次删除都会进行全表扫描以查找要删除的记录,而当发生这种情况时,其他删除必须等待。 如果你在Param1上有一个索引,那么它的处理速度会快得多,你就不会看到你现在的阻塞。

如果你有死锁,系统将杀死一个涉及的进程,否则什么都不会处理; 如果表格很大,那么事情就会处理,但事情会很慢。

我不认为你会陷入僵局(这不是我的专业领域),但明确的交易可能是更好的选择。 此代码会想到一个场景如下

对该过程的两个并发调用以Param1值5执行,同时删除然后同时插入,因此现在您有两个Param1值为5的记录。根据您的数据一致性要求,这可能会或可能不会引起您的关注。

您可以选择实际执行更新,如果没有行受影响(请检查@@ rowcount),然后在事务中执行Insert all。 或者更好的是,请查看Merge以在单个语句中执行插入/更新操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM