我有一個相當複雜的問題,導致我的數據庫中有重複的記錄。如何修復Django的get_or_create()導致數據重複的併發性
我在nginx 1.0.5上運行了uwsgi(4名工人)和Django 1.4.5。問題是,一些客戶端issueing重複請求相同的路徑,如所示下面nginx的日誌:
10.205.132.51 - - [26/Aug/2013:16:59:41 -0300] "GET /path/to/ HTTP/1.1" 499 0 "http://mydomain.com.br/path/" "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20100101 Firefox/21.0"
10.205.132.51 - - [26/Aug/2013:16:59:41 -0300] "GET /path/to/ HTTP/1.1" 200 7372 "http://mydomain.com.br/path/" "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20100101 Firefox/21.0"
這些請求被同時處理,而在像下面這種觀點的情況下,我進入比賽狀態其中都get_or_create
找到任何結果,都創建一個新的對象:
with transaction.commit_on_success():
f, created = cls.objects.get_or_create(
key1=value1,
key2=value2,
defaults={...})
你問之前,沒有,這兩個鍵不是在數據庫unique_together
。
這兩個請求都返回來自Django的200
狀態碼,但是nginx會丟棄一個,導致409
狀態碼(衝突)。 transaction.commit_on_success()
部分是一個減少的嘗試,但沒有解決問題。
我也嘗試了基於緩存的鎖,使用此功能:
@contextmanager
def cache_exclusive(name, timeout=10):
""" found at http://coffeeonthekeyboard.com/simple-out-of-process-lock-with-python-and-memcached-2-985/ """
key = 'cache_lock:%s' % name
lock = cache.add(key, True, timeout=timeout) # Fails if key already exists.
yield lock # Tell the inner block if it acquired the lock.
if lock: # Only clear the lock if we had it.
cache.delete(key)
和獨特的名字與這個用法:
with cache_exclusive('key1 and key2') as granted:
if not granted:
return
# do the get_or_create stuff...
但也沒打釘。您對如何處理這些重複請求有任何建議嗎?
您正在使用什麼數據庫? – pvilas
忘了提及。它是InnoDB引擎的mysql。 –
也許你還想分享你正在努力實現的目標,因爲在數據庫級別解決問題可能會有另一種解決方案。 –