【问题标题】:Django nested Transaction.atomic not rolled backDjango 嵌套 Transaction.atomic 未回滚
【发布时间】:2025-12-22 21:50:16
【问题描述】:

我在两个不同的数据库中有两个逻辑连接的实例。我希望它们都被保存或回滚。但是,如果我在外部块中引发异常 - 嵌套的 Transaction.atomic 不会回滚,但为什么呢?

来自文档:

atomic 块可以嵌套。在这种情况下,当一个内部块 成功完成,它的效果仍然可以回滚,如果 稍后会在外部块中引发异常。

def __commit_to_db(self, mesure, mdm_mesure):
    try:
        with transaction.atomic():
            mesure.save()
            with transaction.atomic(using='mdm'):
                mdm_mesure.save()
            raise Exception('oops')
    except (KeyboardInterrupt, SystemExit):
        raise
    except BaseException as error:
        MainLoger.log_error(error)
    return

【问题讨论】:

  • 对于数据库错误处理,您可以使用 Exception 而不是 BaseException。这是一种更好的做法来缩小可能的错误并仅处理这些错误。

标签: python django django-orm


【解决方案1】:

事务是数据库级别的功能。因此,尽管您嵌套了 Python 代码,但每个数据库实际上都在获得自己的事务,而彼此独立。 Django 中没有跨数据库的嵌套事务。

您必须以某种方式重组您的代码。例如,将您的代码放在两个 atomic() 块中会起作用:

try:
    with transaction.atomic():
        with transaction.atomic(using='mdm'):
            mesure.save()
            mdm_mesure.save()

            # neither transaction will commit
            raise Exception('oops')
except Exception:
    pass

【讨论】: