2011-01-31 11 views
11

私は、特定の状況でトランザクションをどのように処理するべきかについて少し混乱しています。commit_on_successはどのようにネストされていますか?

from django.db import transaction 

@transaction.commit_on_success 
def process_post(): 
    #do stuff with database 
    for reply in post_replies: 
     process_post_reply(reply) 

@transaction.commit_on_success 
def process_post_reply(reply): 
    #do stuff with database 

私はprocess_post_reply()が失敗した場合に何が起こるかを知りたい:

は、私はこれに沸くいくつかのコードを持っています。

どのようにcommit_on_successのハンドルがネストされていますか?それぞれprocess_post_reply()をコミットすることを理解するか、process_post()ロールバック全体が失敗した場合はそれを受け取りますか?ここで

答えて

11

は、それのソースコードです:https://github.com/django/django/blob/1.2.4/django/db/transaction.py#L286

そしてenter_transaction_managementは、スレッドスタックに新しいトランザクション処理モードを置くのと同じくらい簡単です。

したがって、process_post_reply()が失敗した場合(つまり例外が発生した場合)、トランザクションは完全にロールバックされ、例外はさらにprocess_post()から上方に伝播しますが、ロールバックするものはありません。

process_post_reply()が失敗した場合は、process_post()全体がロールバックされません。データベースレベルでCOMMITとROLLBACKだけが魔法です。つまり、ロールバックされるのは、最後にコミットされた後のDB process_post_reply()。残念ながらMySQLの5.xのは、同様にそれらをサポートしていても、唯一のPostgreSQLバックエンドで利用可能です -

要約、私はあなたがはおそらくtransaction savepointsでサポートされている、process_post周りに1つだけcommit_on_success()で必要なものだと思います。

EDIT 2012年4月10日:MySQLのセーブポイントのサポートは今available in Django 1.4

EDIT 2014年7月2日です:トランザクション管理を完全にはDjango 1.6で書き直されました - https://docs.djangoproject.com/en/1.6/topics/db/transactions/commit_on_successが廃止されました。トランザクション管理上のより多くの制御を得るために

3

、それはtransaction.commit_manually()を使用するために良いことだ:ここでは

@transaction.commit_on_success 
def process_post(reply): 
    do_stuff_with_database() 
    for reply in post_replies: 
     process_post_reply(transaction_commit_on_success=False) 

def process_post_reply(reply, **kwargs): 
    if kwargs.get('transaction_commit_on_success', True): 
     with transaction.commit_manually(): 
      try: 
       do_stuff_with_database() 
      except Exception, e: 
       transaction.rollback() 
       raise e 
      else: 
       transaction.commit() 
    else: 
     do_stuff_with_database() 

あなたは、状況に応じて決定し、トランザクションをコミットするか、することはできません。

関連する問題