繁体   English   中英

使用 ExecuteNonQuery 时 Parallel.Foreach 死锁?

[英]Deadlock in Parallel.Foreach while using ExecuteNonQuery?

我在使用 Parallel.Foreach 时遇到死锁错误。 我在数据表中有 1000 条记录,我创建了 5 个线程来处理它。 但是当我运行这个控制台应用程序时,在处理了一些记录之后,它会创建一个死锁,并且不会处理其他记录。 这是我的代码:

Parallel.ForEach(dt1.AsEnumerable(), new ParallelOptions { MaxDegreeOfParallelism = 5 }, dr =>
{
    cmd1.CommandText = $"Update AuditMessage set Status=1" +
        $" where SXAEASCoreAuditMessageID ='{Convert.ToString(dr["AuditMessageID"])}' ";
    cmd1.CommandType = CommandType.Text;
    cmd1.Transaction = trans;
    cmd1.ExecuteNonQuery();                          
});

为什么会锁定?

您的问题可能不是数据库并发,而是您用于每个线程的 cmd1 object 上的并发。

您需要为每个线程或在每次迭代中创建一个新的 SqlCommand。

Parallel.ForEach(dt1.AsEnumerable(), new ParallelOptions { MaxDegreeOfParallelism = 5 }, dr =>
    {
                  using(var cmd = new SqlCommand(connection))
                  {
                     cmd.CommandText = $"Update AuditMessage set Status=1 where SXAEASCoreAuditMessageID ='{Convert.ToString(dr["AuditMessageID"])}' ";
                     cmd.CommandType = CommandType.Text;
                     cmd.Transaction = trans;
                     cmd.ExecuteNonQuery();
                  }                          
    });

行/表锁定的一些基础知识。

如果您在 SQL 服务器上执行此操作,那么您在此并行处理中创建的开销大于速度。 修改的每一行都将被 DBMS 锁定,最终,当开销变高时,它将开始一个表锁定,让您的线程无论如何都按顺序工作。

所以,这里忘了parallel.foreach,让数据库做效率优化

您可以 select 将 AuditMessageIds 放入一个列表中。 然后将其切成 100 块左右,然后进行更智能的更新查询,例如批量更新状态 1 的查询。

where SXAEASCoreAuditMessageID IN ...

暂无
暂无

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

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