2013-01-22 16 views
1

我正在開發一個帶有MySQL和Entity Framework的ASP.NET/C#中的web應用程序。我想使用一些計數器列,這些列會經常通過增加值+1來更新。我有一個計數器列所在的產品表。我有兩個問題:使用MySQL,ASP.NET和Entityframework實現原子計數器

1)我應該使用計數器的第二個表嗎? - 主產品表會頻繁讀取,如果我經常更新行可能會損害性能,因爲每次更新計數器時我都會鎖定行(我使用InnoDB)

2)什麼是使用MySQL和Entity Framework在一行上創建+1遞增的最佳方式。我不介意這個計數器是100%準確的,所以如果有一些更新衝突,我可以抓住它們,但我可以在沒有更新的情況下通過。我認爲大部分更新將會很快完成,幷包含在更新中。

我正在使用一些代碼來實現這一點,通過利用靜態變量來防止頻繁寫入數據庫。

代碼:

if (Global.DataCounters != null) 
    { 
     if (Global.DataCounters.ContainsKey(id)) 
     { 
      int new_value = ++Global.DataCounters[id]; 
      Global.DataCounters.Remove(id); 
      Global.DataCounters.Add(id, new_value); 

      // check datatime 

      if ((DateTime.Now - Global.LastFlushed).Minutes > 10) 
      { 
       // update counter in db and reset data 

       Global.LastFlushed = DateTime.Now; 
      } 
     } 
     else 
     { 
      // first time view of a device, set to zero views 
      Global.DataCounters.Add(id, 1); 
     } 

    } 
    else 
    { 
     Global.DataCounters = new Dictionary<int, int>(); 
    } 

的Global.asax:

public static Dictionary<int, int> DataCounters = new Dictionary<int,int>(); 
public static DateTime LastFlushed; 

void Application_Start(object sender, EventArgs e) 
{ 
    LastFlushed = DateTime.Now; 
    RegisterRoutes(System.Web.Routing.RouteTable.Routes); 
} 

你是否認爲這是一個很好的執行?

感謝

回答

1

的計數器二表只會是有益的,如果說顯著產品表中讀取(比如> 50%)不需要計數器的信息。否則,你總是會加入兩張桌子,使你的閱讀成本很高。

基於MySQL doc:對於更新計數器,如果您的WHERE條件使用唯一索引來搜索唯一行(更新),那麼只會執行行級鎖定(並且不會執行間隙鎖定)。這對你的情況來說是最好的情況(假設產品ID可以用作唯一索引)。我會建議使用Entity SQL來激發Update語句(或者調用一個可以做同樣的事情的SP)。

如果您只想使用實體術語(無EntitySQL或SP),那麼不要使用事務範圍進行此特定操作 - 這樣,選擇用於提取產品實體將不會鎖定,並且SaveChanges將是單個更新語句遞增計數器。當然,在事務之外使用兩個語句意味着更新可能會失敗(假設您有一些可用於樂觀併發檢查的時間戳列),但您已指出它是可接受的。

最後,如果在增加計數器時事務是不可避免的,則儘量縮短它們並嘗試使用較低的隔離級別,例如Read Committed