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