[英]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.