2015-06-28 37 views
0

我有這樣增量更新mysql中的列值。併發問題?

update pageviews set count = count + 1 where pageid = $pageid 

這種說法是每一個網頁被視爲一次執行查詢。因此,每次查看頁面時列計數都會增加。

我的表是InnoDB類型。

假設每秒可能發生數千次綜合瀏覽量,這是不是可擴展的?我可以遇到併發問題嗎?像查詢鎖定等?

有人告訴我,我應該使用隊列來達到這個目的。爲什麼我需要使用隊列?在什麼樣的情況下我的數據可能會被損壞或者可擴展性會成爲一個問題?

回答

1

InnoDB在商品硬件上開箱即用,每秒處理大約100個這樣的語句。沒有併發或鎖定問題,只是性能問題。

  • innodb_flush_log_at_trx_commit默認爲1,以確保安全。但是這需要每個事務的日誌的磁盤I/O。 2要快得多,而且合理的妥協。 (碰撞可能會失去一秒鐘的交易。)

  • 您的UPDATE可能是autocommited?或者在交易本身?它可以以任何方式進行批處理嗎?如果是這樣,那會減少開銷。

  • pageview由Web服務器處理,是否正確?它能在實際寫入表格之前收集一些pageids嗎?即使它收集了一秒鐘,這可能是一個顯着的加速。如果您這樣做,一定要將IN列表排序在update pageviews set count = count + 1 where pageid IN (...)。這將減少死鎖的可能性。

  • 處理您的UPDATE錯誤。 (否則,您的數據將是「錯誤」或「損壞」。)

1

除了@裏克的回答是:我不知道隊列如何能夠幫助你,我唯一的想法就是送所有頁面事件將您擁有多個使用者的地方排隊,每個事件都會更新自己的數據庫,並在稍後彙總結果。此外,隊列允許您在短時間內處理大量負載時處理一些峯值負載 - 在這種情況下,您不會阻止數據庫更新,而是將事件放入內存中,稍後會處理這些事件,但它不會幫助您如果您無法在正常負載下處理事件流。

還有一個建議 - 如果您每秒有幾千次綜合瀏覽量,那麼您可能不需要預先跟蹤它們(如果它不是結算),那麼如果您有一個有狀態的服務器:

onPageView() { 
    cnt += 1 
    if (cnt == 1000) {update table set views = views + 1000; counter = 0;} 
} 

(不要忘了線程安全)

甚至

onPageView() { 
    value = random(0, 1000); 
    if (value == 0) { 
     update table set views = views + 1000 
    }  
} 

,你不需要關心狀態,並且您減少寫入的數1000次