【问题标题】:How does commit_on_success handle being nested?commit_on_success 如何处理嵌套?
【发布时间】:2011-06-18 15:11:59
【问题描述】:

我对在特定情况下应该如何处理交易感到有些困惑。

我有一些代码可以归结为:

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() 回滚?

【问题讨论】:

    标签: database django django-orm


    【解决方案1】:

    这是它的源代码: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()

    总结一下,我认为您需要的只是process_post 周围的单个commit_on_success(),可能由transaction savepoints 支持-不幸的是,尽管MySQL 5 仅在PostgreSQL 后端可用.x 也支持它们。

    2012 年 4 月 10 日编辑:对 MySQL 的保存点支持现在是 available in Django 1.4

    2014 年 7 月 2 日编辑:事务管理已在 Django 1.6 中完全重写 - https://docs.djangoproject.com/en/1.6/topics/db/transactions/commit_on_success 已弃用。

    【讨论】:

      【解决方案2】:

      为了更好地控制事务管理,最好使用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()
      

      这里你可以根据情况决定是否提交事务。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-19
        • 2017-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-01
        • 2010-11-19
        • 1970-01-01
        相关资源
        最近更新 更多