我正在使用SQL Server 2008 Enterprise。并使用ADO.Net + C#+。Net 3.5 + ASP.Net作为客户端访问数据库。当我访问SQL Server 2008表时,我总是从我的C#+ ADO.Net代码调用存储过程。
我在表FooTable上有3个操作。并且多个连接将在序列中同时执行它们,即执行删除,执行插入然后执行选择。 每个声明(删除/插入/选择)在单个商店过程中是单独的单个事务。
我的问题是删除语句是否可能发生死锁? 我的猜测是,如果多个连接在相同的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)
答案 0 :(得分:2)
我会将Param1的索引添加到FooTable;没有它,DELETE正在进行全表扫描,这会产生死锁问题。
修改强>
根据您的活动详细信息,它看起来不像您有死锁,您有阻止,许多删除正在排队,同时发生一次删除。同样,对Param1进行索引可以缓解这种情况,如果没有它,每次删除都会进行全表扫描以查找要删除的记录,而当发生这种情况时,其他删除必须等待。如果你在Param1上有一个索引,它会更快地处理,你就不会看到你现在的阻塞。
如果你有死锁,系统会杀死其中一个涉及的进程,否则什么都不会处理;如果表格很大,那么事情就会处理,但事情会很慢。
答案 1 :(得分:1)
我认为你不会陷入僵局(这不是我的专业领域),但明确的交易可能是更好的选择。使用此代码时会想到的场景如下
对该过程的两个并发调用以Param1值5执行,同时删除然后同时插入,因此现在您有两个Param1值为5的记录。根据您的数据一致性要求,这可能是也可能不是你。
您可以选择实际执行更新,如果没有行受影响(请检查@@ rowcount),然后在事务中执行Insert all。或者更好的是,请查看Merge以在单个语句中执行插入/更新操作。