Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正在尝试防止此死锁在SQL Server上的.NET代码中发生_C#_.net_Sql Server_Deadlock - Fatal编程技术网

C# 正在尝试防止此死锁在SQL Server上的.NET代码中发生

C# 正在尝试防止此死锁在SQL Server上的.NET代码中发生,c#,.net,sql-server,deadlock,C#,.net,Sql Server,Deadlock,在对某些C代码进行集成测试期间,死锁正在发生,这些C代码正在针对SQL Server测试SQL查询 软件:SQL Server 2012 数据库:读提交隔离设置为ON 我有两个测试,这两个测试是相互斗争的,因为这是并行发生的 测试1伪C代码 using (start a new transaction) { foreach Person in the People-Collection { Insert this Person into the DB and gr

在对某些C代码进行集成测试期间,死锁正在发生,这些C代码正在针对SQL Server测试SQL查询

软件:SQL Server 2012 数据库:读提交隔离设置为ON 我有两个测试,这两个测试是相互斗争的,因为这是并行发生的

测试1伪C代码

using (start a new transaction)
{
    foreach Person in the People-Collection
    {
        Insert this Person into the DB and grab the ID of this inserted person.
        => INSERT INTO [dbo].[People] (...) VALUES (...);
           SELECT CAST(SCOPE_IDENTITY() AS INT);
    }

    Now, count how many people are in the DB right now (because there might have been more, from before we inserted these temp people).
        => SELECT COUNT(PersonId) FROM [dbo].[People]
}
// end transaction (which rolls back because of no explicit transaction.commit)
测试2

using (start a new transaction)
{
    Update a person
    => UPDATE [dbo].[People]
       SET    .....
       WHERE  PersonId = @personId
}
// end transaction which auto rolls back.
因此,我猜测以下情况正在发生:

Test1运行INSERT/SELECT Test2运行更新,等待test1完成 Test1完成,但现在运行SELECT计数。。 出于某种原因,test1正在等待test2完成更新,但test2无法更新,原因我无法想象

我本以为会发生以下情况:

Test1开始在事务中运行和运行。 Test2开始运行。。并注意到有一个事务正在运行,所以它要么等待该事务完成,要么可以发现它的更新与test1的事务无关,所以它会更新。 Test1最终完成。 显然,我不明白发生了什么:

索引 死锁图列出了一个特定的索引,这是导致死锁的原因。以下是索引:

ALTER TABLE [dbo].[People] ADD  CONSTRAINT [IX_People_Name] UNIQUE NONCLUSTERED 
(
    [Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
有人能给我一些建议如何解决这个问题吗

注意:包含完整的死锁图作为参考

编辑1:使用语句代码添加,以便更好地理解逻辑/流。
编辑2:添加了索引架构/代码

您在名称列上有一个索引,因此为了锁定/IO的目的,更新行为类似于删除+插入

死锁图显示Test1正在等待获取RangeS-S锁以计数所有行,同时在插入的行上保持RangeX-X锁。它需要在整个表上使用一个共享锁来计算行数,并为插入的行使用一个独占锁,但不确定为什么要使用范围锁

同时,Test2正在等待获取RangeI-N锁以插入新的名称行,同时在删除的旧名称行上保持X锁

我建议采取以下措施之一:

在主键PersonId上创建一个狭窄的唯一索引?字段-此索引不需要锁定更新,可以用于快速计数*而且维护成本非常低。它还提高了外键完整性检查的并发性和性能,要使其生效,必须重新创建FK-s引用[People]表。 如果业务需求允许,请更改计数查询的锁定-例如,使用WITHREADCOMMITTED表提示或在提交插入后执行此操作。 在插入之前运行count查询并按插入的行计数递增。这可能不利于并发性,因为它持有整个表的共享锁
>>结束由于没有显式事务而回滚的事务。提交是否正在执行显式回滚?否。代码位于.net使用范围内,因此它会自动回滚,因为没有显式提交;这个表上有什么索引?[dbo].[People]中SELECT COUNTPersonId的查询计划是什么样子的?不要使用SELECT CASTSCOPE\u标识。使用插入的输出…您可以在selectHi@pent中添加nolock提示-感谢您的回答。你有没有可能详细说明你的答案。我现在真的不明白那是什么意思。这些锁好吗?他们应该这样做吗?有没有其他的建议,我可以如何改善事情,以消除这些问题?我试图了解你的答案的技术要点。。。因此,当我完成这项工作时,我将发布一个奇怪的问题。首先-当我没有针对特定字段执行任何WHERE子句时,为什么代码会使用IX_People_Name作为索引?需要为新的/更改的行更新索引。count查询很可能使用索引,因为它是表中最小最窄的索引-这是枚举所有行的最快方法。为什么count使用IX_People_Name索引而不是主键?主键不是该表上最小最窄的索引吗?主键很可能是聚集索引-它包含所有列,即整个表。