我对如何处理特定情况下的交易感到有点困惑。
我有一些可归结为此的代码:
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()
回滚?
这是它的源代码: 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
,可能支持 交易保存点 - 遗憾的是,它只在PostgreSQL后端可用,即使MySQL 5.x也支持它们。
编辑2012年4月10日:现在支持MySQL的Savepoint 在Django 1.4中可用
编辑2014年7月2日:事务管理已在Django 1.6中完全重写 - https://docs.djangoproject.com/en/1.6/topics/db/transactions/ 和 commit_on_success
已被弃用。
为了获得对事务管理的更多控制,最好使用它 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()
在这里,您可以根据具体情况决定是否提交交易。