2016-05-29 60 views
1

我有一個單線程的5個芹菜工人。它通過django的ORM抓取網站並將域名保存到數據庫。芹菜/ django重複關鍵違規

這裏大致是它的樣子:

domain_all = list(Domain.objects.all()) 
needs_domain = set() 

for x in dup_free_scrape: 
    domain = x['domain'] 
    if any(domain.lower() == s.name.lower() for s in domain_all): 
     x['domainn'] = [o for o in domain_all if domain.lower() == o.name.lower()][0] 
    else: 
     print('adding: {}'.format(domain)) 
     needs_domain.add(domain) 

create_domains = [Domain(name=b.lower()) for b in needs_domain] 
create_domains_ids = Domain.objects.bulk_create(create_domains) 

可能不是最好的方式,但它在一個字典(dup_free_scrape)針對已經在數據庫中的所有域檢查域。

它可以走了幾百甚至上千遇到錯誤之前,但有時它的作用:

Task keywords.domains.model_work[285c3e74-8e47-4925-9ab6-a99540a24665] raised unexpected: IntegrityError('duplicate key value violates unique constraint "keywords_domain_name_key"\nDETAIL: Key (name)=(domain.com) already exists.\n',) django.db.utils.IntegrityError: duplicate key value violates unique constraint "keywords_domain_name_key"

對於這個問題,我能想到的唯一理由是:一個線程保存域DB,而另一個是在上面的代碼中間?我不能找到任何好的解決方案,但這裏是和想法(不知道是否有任何好處):在事務中包裝整個事情,如果數據庫引發錯誤簡單重試(查詢數據庫爲「Domain.objects.all() 「再次)。

回答

0

如果您正在批量創建這些記錄並且存在多個線程,那確實非常類似於由不同線程插入相同數據引起的。你真的需要多線程來處理這個嗎?如果是,您可以嘗試

create_domains = [] 
create_domain_ids = [] 

for x in dup_free_scrape: 
    domain = x['domain'] 
    new_domain, created = Domain.objects.get_or_create(name = domain.lower() 
    if created: 
     create_domains.append(domain.lower()) 
     created_domain_ids.append(new_domain.pk) 

請注意,這是所有的代碼。不需要在開始時選擇所有的查詢。 Domain.objects.all()將會非常低效,因爲您正在閱讀整個表格。

另請注意,您對x['domainn']的列表理解似乎是完全多餘的。

create_domainscreate_domain_ids列表可能不需要,除非您想跟蹤正在創建的內容。

請確保您有正確的域名索引。來自get_or_create文檔:

This method is atomic assuming correct usage, correct database configuration, and correct behavior of the underlying database. However, if uniqueness is not enforced at the database level for the kwargs used in a get_or_create call (see unique or unique_together), this method is prone to a race-condition which can result in multiple rows with the same parameters being inserted simultaneously.

+0

有很多意義,但不會get_or_create查詢數據庫很多嗎?因爲有時它在時間上添加了超過100個域名。謝謝 – JanRainMan

+0

只有100個查詢可能比循環整個可能有數十萬個表的查詢更有效率。 – e4c5

+0

除了在原始代碼中,由於任何條件檢查,您實際上都有嵌套循環。 – e4c5