for 循环导致 C# 和存储过程中的死锁

for loop causing a deadlock in c# and stored procedure

提问人:user22144337 提问时间:9/29/2023 最后编辑:Thom Auser22144337 更新时间:9/29/2023 访问量:100

问:

我花了很长时间试图解决这个僵局。daedlock 位于_dbcontext.DeleteTags(tag);

和转到同一个图形表(这就是我无法使用 EF 删除/插入的原因,因为它尚不受支持)但是,死锁正在发生,可能是因为 for 循环。你能建议如何分类吗?AddTagsDeleteTagsDeleteTags

public async Task UpdateScenario()

try
{
    await _businessCore.TransactionManager.Begin();

    _dbcontext.MyData.Update(scenario);

    foreach (var tag in newtags)
    {
        tag.LabelGroupId = labelGroup.LabelGroupId;
        tag.LabelId = (await _dbcontext.AddTags(tag)).LabelId;
        tag.Attributes.ToList().ForEach(z => z.LabelId = lbl.LabelId);
    }

    foreach (var tag in deletedTags)
    {
        await _dbcontext.DeleteTags(tag);
    }

    await Validation.SaveChangesWithValidation(_dbcontext);
    await _businessCore.TransactionManager.Commit();
}
catch
{
   await _businessCore.TransactionManager.Rollback();
   throw;
}

DeleteTag功能

public async Task DeleteTag(Tags tag)
{
    await this.Labels.FromSqlInterpolated($"exec uspDeleteTag {tag.LabelId}").ToListAsync();
}

我的存储过程:

CREATE PROCEDURE [dbo].[uspDeleteTags] 
    (@LabelId INT)
AS
BEGIN
    DELETE FROM tgphLabel 
    OUTPUT DELETED.LabelId, DELETED.LabelTypeId, DELETED.LabelGroupId
    WHERE LabelId = @LabelId;
END
C# 死锁 SQL-Server-2019

评论

0赞 user22144337 9/29/2023
@jarlh我正在使用 SQL Server Microsoft。感谢您查看此内容。
1赞 siggemannen 9/29/2023
你在tgphLabel上有多个索引吗?您可以使用 tablock,或者创建一个可以一次删除多个标签的过程,而不是执行循环删除
1赞 Jonathan Willcock 9/29/2023
我怀疑问题在于你有一个围绕所有内容的事务,但是当你调用存储过程时,这不是事务的一部分。我建议编写一个 SP,在 SP 本身的事务中同时执行所有插入和所有删除。
1赞 TomTom 9/29/2023
题外话 - 真正的 SQL 专家正在 dba.stackexchange.com 这是应该重定向的地方。鉴于死锁是数据库级别的操作,因此不应考虑使用 C#,而应提供完整的 SQL 级别跟踪信息。你知道,有一个 profilder,用于 sql server。
1赞 seanb 9/29/2023
这不会修复死锁(或者可能不会) - 但是如果您在表中没有索引,则意味着每个 DELETE 命令都必须读取整个表以识别与 LabelID 匹配的所有相关行。使用 LabelId 上的索引,除非表非常小,否则至少读取次数将最小化(并且会加快此过程)。LabelIdtgphLabel

答: 暂无答案