2017-06-14 100 views
2

我已經寫了下面的一段代碼執行從多個線程表批量更新:C#不死鎖

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批次更新從一個有效的方式從多個線程表?

有人可以幫我嗎?

回答

-1

嘗試

鎖 { .... }

這將完成,當一個進程正在執行大括號中的代碼,這將導致其他進程要等到第一個完成。這樣,一次只有一個進程會執行該塊。

+0

'lock'不會同步多個進程,即使這樣做,數據庫也可以完全與完全不同的機器進行交互。同步需要在數據庫級別進行處理。 – Servy

+0

@Servy,我認爲這個場景是一個進程中的多線程,不是嗎? – dsolimano

+0

@dsolimano不,它不是。這是一個數據庫拋出錯誤,因爲與數據庫的其他一些連接的某些交互造成了死鎖。數據庫對於單個進程不是本地的。 – Servy

0

死鎖消息來自SQL Server - 這意味着您的一個連接正在等待另一個資源鎖定的資源,並且第二個連接正在等待第一個資源上的資源。

如果您嘗試更新同一個表,您很可能會遇到一個簡單的SQL鎖定問題,並且與C#沒有任何關係。您需要更徹底地思考在多個線程上執行批量更新的含義;它可能(取決於你正在更新的表的百分比)更好地在單個連接上執行此操作,並使用隊列式機制來解除各個調用的衝突。

5

我對這個API瞭解不多,但快速閱讀建議您可以嘗試一些事情。我會按照列出的順序嘗試它們。

  1. 使用較小batch size,和/或設定的批次超時更高。這將讓每個線程輪流。

  2. 使用temporary table。這將允許線程獨立工作。

  3. options設置爲使用表鎖。如果你鎖定整個表,不同的線程將無法鎖定不同的行,所以你不應該得到任何死鎖。

+0

如果OP執行你的建議#3,是不是會使他/她使用多個線程毫無意義? – hatchet

+0

我猜「多線程」問題是由於OP使用ASP.NET,並且每個HTTP請求有一個線程而引起的。但是你是正確的,它會導致更新以串行方式而不是並行方式完成。使用表鎖將允許OP避免必須編寫他自己的排隊系統。另一方面,這些批量操作可能會導致HTTP請求超時。 –

+0

我錯過了ASP.Net標記。我在想線程是有意的,並由OP的代碼創建。你的回答是有道理的。 – hatchet