我对如何处理特定情况下的交易感到有点困惑。
我有一些可以归结为此的代码:
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()
回滚?
答案 0 :(得分: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,这意味着回滚的是只有在最后一次提交process_post_reply()
之后写入数据库的内容。
总结一下,我认为您需要的内容只是commit_on_success()
周围process_post
,可能由transaction savepoints支持 - 遗憾的是,它只在PostgreSQL中可用后端,即使MySQL 5.x也支持它们。
编辑2012年4月10日:现在对MySQL的Savepoint支持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
已被弃用。
答案 1 :(得分: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()
您可以根据情况决定是否提交交易。