2012-01-31 15 views
0

Djangoの並行処理に関する多くのトピックがありますが、それらの多くをチェックした後、私はトランザクションに関して私の答えを見つけたとは思いません。Django - Postgresql:トランザクションと並行性

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) 

を私はまた、メンバーとベットの間の関係であるテーブルのお金を持っています。それは私の問題に直接リンクされていませんが、どの並行性の問題によっても影響を受けることはないので、それを監視するのに役立ちます。つまり、メンバーのフィールドマネーとベットのtotal_moneyが正しいかどうかをテストするために、私はテーブルマネーを数えなければなりません。

私はテーブルマネーだけに頼ることはできませんが、私はそれらを使用して多くをフィルタリングするので、私のフィールドが正しいようにする必要があります。

私の最初のベット機能は、このようなものでした(さらに多くのテーブルを変更しただけです)。

このバージョンは、1回のトランザクションで初めてクラッシュするまでうまく機能していました。 この場合、clean()やfull_clean()を使用することができないため、bid()の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()オブジェクトを手動トランザクション内で使用することはできません(意味があります)。私は多くの並行性の問題で終わった。私は2つだけのソリューションを参照

  • はお金だけを作成するには、入札()/トランザクション中にオブジェクトが、その後、非同期Worker(?セロリ)のメンバーとベットで関連分野を更新しています。

  • 入札()/取引(Redis?)のリストを作成し、お金関連のフィールドを変更するすべての取引を同期させます。

アムは、私が明白かつ容易にソリューションを逃しますか? そうでない場合は、どのテクノロジを使用することをお勧めしますか?

答えて

1

これは機能しますか?

 
@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) 

+0

少なくとも、トランザクション+ Fオブジェクトを使用して私のバージョンから改善されています。どうもありがとう。私にとっては少し遅れている(私はそれを試してみるために多くの修正がある)が、明日は確実に試してみる。 – Ashe

+0

私のすべてのテストは、そのソリューションでは緑色です。私はすぐにそれをプッシュし、並行性の問題がこれ以上検出されないかどうかを確認します。私が見る唯一の欠点は: - 私は明らかに値が更新されていないので、きれいな関数を使うことはできません。 - プレセーブ機能とポストセーブ機能がアップデートで機能しない(アップデートが本当に1つの項目を変更するために使用されると思われるのだろうか) - 私がメンバーに持っていたmoney_maxフィールドの更新を削除しなければならなかった表。私は、あなたがF:update(money_max = max(F( 'money')、F( 'money_max')))を使ってそのようなことを書くことはできないと思います。私は自分のSQLクエリを書くだけです。 – Ashe

+1

メンバ= Member.objects.filter(user__id = member_pk) members.update(money = F( 'money') - value) members.filter(money_max__lt = F( ' (money_max = F( 'money')) – Ashe

関連する問題