【问题标题】:C# performing bulk update on table from multiple threads without a deadlockC#从多个线程对表执行批量更新而没有死锁
【发布时间】:2017-06-14 20:26:27
【问题描述】:

我写了如下一段代码:

public void BulkUpdateItems(List<Items> items)
        {
            var bulk = new BulkOperations();

            using (var trans = new TransactionScope())
            {
                using (SqlConnection conn = new SqlConnection(@"connstring"))
                {
                    bulk.Setup()
                    .ForCollection(items)
                    .WithTable("Items")
                    .AddColumn(x => x.QuantitySold)
                    .BulkUpdate()

                    .MatchTargetOn(x => x.ItemID)
                    .Commit(conn);

                }
                trans.Complete();
            }
        }

使用 SQLBulkTools 库...但这里的问题是,当我一次从多个线程运行此过程时,我在死锁上运行...

并且错误表明某个进程 ID 已死锁或类似情况......

有没有其他方法可以有效地从多个线程批量更新 1 个表?

谁能帮帮我?

【问题讨论】:

    标签: c# asp.net sql-server multithreading bulkupdate


    【解决方案1】:

    我对那个 API 了解不多,但快速阅读建议您可以尝试一些事情。我会按照列出的顺序尝试它们。

    1. 使用更小的batch size,和/或将批处理超时设置得更高。这将使每个线程轮流运行。

    2. 使用temporary table。这将允许线程独立工作。

    3. options 设置为使用表锁。如果你锁定整个表,不同的线程将无法锁定不同的行,所以你不应该遇到任何死锁。

    【讨论】:

    • 如果 OP 执行您的建议 #3,那他/她使用多个线程是否毫无意义?
    • 我猜“多线程”问题是由 OP 使用 ASP.NET 引起的,并且每个 HTTP 请求都有一个线程。但是您是正确的,因为它将导致更新以串行方式而不是并行方式进行。使用表锁将允许 OP 避免编写自己的排队系统。另一方面,这些批量操作可能会导致 HTTP 请求超时。
    • 我错过了 ASP.Net 标签。我在想线程是故意的,是由 OP 的代码创建的。你的回复很有道理。
    【解决方案2】:

    死锁消息来自 SQL Server - 这意味着您的一个连接正在等待被另一个锁定的资源,而第二个连接正在等待第一个连接的资源。

    如果您尝试更新同一个表,您可能会遇到一个简单的 SQL 锁定问题,并且与 C# 没有任何关系。您需要更彻底地考虑在多个线程上进行批量更新的含义;它可能(取决于您正在更新的表的百分比)最好在单个连接上执行此操作并使用队列样式的机制来消除各个调用的冲突。

    【讨论】:

      【解决方案3】:

      试试

      锁定 { …… }

      这将做的是,当一个进程正在执行花括号内的代码时,它将导致其他进程等待第一个进程完成。这样,一次只有一个进程会执行该块。

      【讨论】:

      • lock 不会同步多个进程,即使这样做了,数据库也可以完全从完全不同的机器上进行交互。同步需要在数据库级别处理。
      • @Servy,我认为场景是一个进程中的多线程,不是吗?
      • @dsolimano 不,不是。这是一个引发错误的数据库,因为与数据库的其他一些连接的某些交互导致了死锁。数据库不是单个进程的本地数据库。
      • @Servy,也许吧。但是,如果这是夜间数据加载的一部分,那么在没有其他数据库用户的时候,这个问题建议但没有说明。 . .完全有可能这个过程自己踩在脚下,我以前自己做过。
      • @dsolimano 当然可以,但是仅仅因为有其他人在场的可能性并不意味着你可以假设没有其他人会在场。当有其他人在场时,仍需要编写代码才能运行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-16
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 2016-04-08
      • 1970-01-01
      相关资源
      最近更新 更多