2015-11-04 28 views
0

我有多個控制檯應用程序,但他們會讀取和插入更新相同的sql表。我使用了transactionscope,但是我收到了這個錯誤 「事務(進程ID)與另一個進程在鎖資源上死鎖,並且被選爲死鎖受害者,重新運行事務。多個控制檯應用程序使用EF objectcontext更新相同的sql表格

我在catch塊中得到一個異常。我怎樣才能避免這種情況? 我知道問題是什麼,但我不確定應該採取什麼樣的解決方案。我在不同的論壇上看到很多問題,但他們都沒有幫助我。

在我的代碼中,一切都很好嗎?

bool isMaster = false; 
tourneyInstanceTrackerId = 0; 
using (JG_RummyEntities dbContext = new JG_RummyEntities()) 
{ 
try 
{ 
using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required,new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead })) 
       { 
bool isAnyMaster = dbContext.TourneyInstanceTrackers.Any(t => t.IsMaster & t.TournamentId == tournamentId); 
TourneyInstanceTracker tourneyInstanceTracker = new TourneyInstanceTracker 
        { 
         TournamentId = tournamentId, 
         IsMaster = !isAnyMaster, 
         CreateDate = DateTime.Now 
        }; 
         dbContext.AddToTourneyInstanceTrackers(tourneyInstanceTracker); 
dbContext.SaveChanges(); 
        var result = dbContext.TourneyInstanceTrackers.Where(t => t.TournamentId == tournamentId) 
          .OrderByDescending(t => t.CreateDate) 
          .Select(t => new { t.IsMaster, t.Id }) 
          .FirstOrDefault(); 
        if (result != null) 
        { 
         isMaster = result.IsMaster; 
         tourneyInstanceTrackerId = result.Id; 
        } 
        transaction.Complete(); 
       } 
      } 
      catch (Exception ex) 
      { 
       Logger.Log("Got exception in SetTournamentInTourneyInstanceTracker : " + ex.Message + ", " + ex.StackTrace + ", "+ tournamentId); 
      } 
     } 

回答

2

IsolationLevel.RepeatableRead就像一個ReaderWriterLockSlim,多線程可以同時讀取記錄,但只要人願意寫你必須等待所有的讀者完成,然後採取排它鎖在對象上,直到你完成寫作。所以想象你有一個程序,它讀取對象「A」等待一會,然後寫入對象「A」。現在讓我們看看程序的兩個副本運行時會發生什麼。

 
Program 1  Program 2 
---------  --------- 
Begin Trans Not Started 
Read A  Begin Trans 
Wait   Read A 
Try Write A Wait 
Try Write A Try Write A 
Try Write A Try Write A 
Try Write A Try Write A 

你可以看到程序1正在等待計劃2但是釋放其讀鎖,計劃2至程序1釋放其讀鎖不能釋放其讀鎖。這兩個等待另一個完成的情況稱爲死鎖

有兩種方法可以解決這個問題,一種是您可以使用更具限制性的IsolationLevel.Serializable,這會阻止其他讀者,直到事務完成。

 
Program 1  Program 2 
---------  --------- 
Begin Trans Not Started 
Read A  Begin Trans 
Wait   Try Read A 
Write A  Try Read A 
End Trans  Read A 
       Wait 
       Write A 
       End Trans 

另外就是你按照異常的建議,這引起你重新運行異常再次功能,直到它獲得通過沒有計劃阻止它的另一個副本的代碼塊。

+0

感謝您的回覆。我將IsolationLevel更改爲Serializable,但這也沒有幫助。這是我得到的錯誤,從商店提供商的數據閱讀器讀取時發生錯誤。有關詳細信息,請參閱內部異常。在System.Data.Common.Internal.Materialization.Shaper'1.StoreRead()。我在互聯網上檢查確實是同樣的錯誤。只是FYI我的SQL表只有4列一個是ID是IDENTITY(1,1)的主鍵,其他三個是bigint類型。 – user1955255

+0

您需要查看內部異常以找出錯誤的原因。 –

+0

正如我所說的那樣,error.System.Data.SqlClient.SqlException(0x80131904)。事務(進程ID 293)在另一個進程的鎖資源上死鎖,並被選爲死鎖受害者。重新運行交易。 – user1955255