我有这样的模型:
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')
一个 View 应该做这样的事情:
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)
我知道这个 View 很丑陋,但它显示了我想做的事情。
现在的问题是,当并发请求出现时,如何保护自己免受竞争条件的影响?锁定表是唯一的方法吗?
Django 1.7.7,MySQL(事务设置为:READ COMMITED)
最佳答案
所以我并没有真正找到答案,因为现在我认为这个想法从一开始就很糟糕。
我最终没有存储 Card 模型,而是选择了带有 LFSR 的模型,并且只将种子存储在 Deck 模型中。这对我来说已经足够了。
供将来引用。您需要一些在 DB 级别失败的东西(如唯一约束),这将引发一些异常,您的逻辑可以在 transaction.atomic()
上下文管理器中识别。
具有READ-COMMITTED
隔离级别的MySQL 适用于get_or_create
。
感谢大家提供的信息。
关于mysql - Django 模型创建时的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29470694/