Django模型创建时的竞争条件

时间:2015-04-06 11:50:16

标签: mysql django concurrency transactions locking

我的模特有:

class Deck(models.Model):
    some_hash = models.CharField(max_length=64)
    store_id = models.CharField(max_length=256)
    tier = models.IntegerField()

class Card(models.Model):
    deck = models.ForeignKey(Deck, related_name='cards')

一个应该做这样的事情的观点:

class GetCardView(ApiView):  # ApiView from Django REST Framework
    response_json = get_some_data_from_external_service(
        request.GET['store_id'], request.GET['tier']
    )  # if this data for a store_id and tier changes a new Deck is needed

    deck, created = Deck.objects.get_or_create(
        some_hash=hashlib.sha256(response).hexdigest(), 
        store_id=request.GET['store_id'], tier=request.GET['tier']
    )
    if created:
        deck.add_cards(response_json)  # adds for e.g. 5 cards

    card = deck.pick_a_card()
    if not card: #  deck depleted
        Deck.objects.create(
            some_hash=hashlib.sha256(response).hexdigest(), 
            store_id=request.GET['store_id'], tier=request.GET['tier']
        )
        deck.add_cards(response_json)  # adds for e.g. 5 cards
        card = deck.pick_a_card()
    return Response(card)

我知道这种观点很难看,但却表明我想做什么 现在问题是如何在并发请求出现时保护我的自己免受竞争条件的影响?锁定表是唯一的方法吗? Django 1.7.7,MySQL(事务设置为:READ COMMITED)

1 个答案:

答案 0 :(得分:0)

所以我并没有真正得到答案,因为我认为这个想法从一开始就很糟糕 我最终没有存储卡模型,我选择了LFSR,只在Deck模型中存储种子。这对我的情况来说已经足够了。

供将来参考。您需要在数据库级别上失败的东西(如唯一约束),这会引发一些可由transaction.atomic()上下文管理器中的逻辑识别的异常。

具有READ-COMMITTED隔离级别的MySQL适用于get_or_create

感谢所有给定的信息。