簡體   English   中英

Django-Postgresql:事務和並發

[英]Django - Postgresql: transaction and concurrency

關於Django並發性有很多主題,但是在檢查了很多主題之后,我覺得在事務處理方面我沒有找到答案。

Django版本1.3.1。 PostgreSQL版本8.4.7。

我的模型的一個非常簡單的版本可能如下所示:

def Member(Model):
  money = PositiveIntegerField(default=0)
  user = OneToOneField(User, related_name='member', primary_key=True)

def Bet(Model):
  total_money = PositiveIntegerField(default=0)

我也有一個表Money,這是Member和Bet之間的關系。 它與我的問題沒有直接聯系,但是可以幫助我監視它,因為它不會受到任何並發問題的影響。 即我只需要數我的表Money來測試Member和Bet的total_money字段的貨幣是否正確。

但是,我不能僅依賴於Money表,我需要我的字段正確無誤,因為我經常使用它們進行過濾。

我對下注功能的首次嘗試是這樣的(只是對更多表進行了很多修改)。

def bid(user_pk, bet_pk, value):
  #create Money object
  member = User.objects.get(user_pk).member
  member.money = F('money') - value
  member.save()
  bet = Bet.objects.get(bet_pk)
  bet.total_money = F('total_money') + value
  bet.save()

這個版本運作良好,直到我在一次交易中第一次崩潰。 我還必須將我的clean()函數中的所有測試復制粘貼到bid()中,因為在這種情況下,我真的不能使用clean()或full_clean()(特別是如果下注提高后,保存成員) 。

因此,我決定嘗試django交易。

@transaction.commit_manually
def bid(user_pk, bet_pk, value):
  try:
    #create money object
    member = User.objects.get(user_pk).member
    member.money -= value
    member.clean()
    member.save()
    bet = Bet.objects.get(bet_pk)
    bet.total_money += value
    bet.clean()
    bet.save()
  except:
    transaction.rollback()
    raise
  else:
    transaction.commit()

但是不可能在手動事務中使用F()對象(這很有意義)。 我最終遇到了很多並發問題。

我只看到兩種解決方案:

  • 僅在bid()/交易期間創建Money對象,然后使用異步工作程序(Celery?)更新Member和Bet中的相關字段。

  • 創建bid()/交易(Redis?)的列表,並使所有修改與貨幣相關的字段的交易都同步。

我是否缺少一個顯而易見且更簡單的解決方案? 如果沒有,您將建議使用哪種技術的解決方案?

這會工作嗎?


@transaction.commit_on_success
def bid(user_pk, bet_pk, value):
    Member.objects.filter(user__pk=user_pk).update(money=F('money') - value)
    Bet.objects.filter(pk=bet_pk).update(total_money=F('total_money') + value)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM