Django nested transactions - “with transaction.atomic()”年的问题是,考虑到这一点...

def functionA():
    with transaction.atomic():
        #save something
        functionB()

def functionB():
    with transaction.atomic():
        #save another thing

如果functionB失败并回滚,functionA也会回滚吗?

Kevin Christopher Henry回答说,"是的,如果在任何一个函数中发生异常,它们都将被回滚."然后他引用了the docs句话,其中说:

原子块可以嵌套.在这种情况下,当内部挡路成功完成时,如果稍后外部挡路引发异常,其效果仍然可以回滚.

这篇文档引用似乎没有解决最初的问题.文档是说,当内部的挡路(即functionB%)成功完成时,如果外部的挡路(即函数A)引发异常,其效果仍然可以回滚.但这个问题指的是相反的情况.问题是,如果内部的挡路(functionB)出现故障,外部的挡路(functionA)是否回滚?这篇文档引文没有提到那个场景.

然而,在文档的下面我们看到了这个例子...

from django.db import IntegrityError, transaction

@transaction.atomic
def viewfunc(request):
    create_parent()

    try:
        with transaction.atomic():
            generate_relationships()
    except IntegrityError:
        handle_exception()

    add_children()

...接下来是 comments ...

在本例中,即使generate_relationships()因违反完整性约束而导致数据库错误,您也可以在add_children()中执行查询,并且create_parent()中的更改仍然存在.

如果我正确阅读了文档,说明对generate_relationships()的调用(类似于原始问题中对functionB的调用)可能会失败,并且在create_parent()add_children()中所做的更改将提交到数据库.这似乎与凯文·克里斯托弗·亨利的回答相矛盾.

令我困惑的是,我在Django nested Transaction.atomic个问题/答案中看到了同样的问题/答案.

我对Django和Stackoverflow都是新手,所以我对阅读文档没有太大的信心,但这似乎与这两种react 相矛盾.我想从更有经验的人那里得到一些澄清.非常感谢你.

推荐答案

以下是具有嵌套事务块和数据库操作XYZ的一些伪代码:

with transaction.atomic():
    X
    with transaction.atomic():
        Y
    Z

如果X引发了一个异常,那么显然没有一个操作会有机会首先提交.

如果Y引发异常-这就是您提到的问题-那么外部挡路也将回滚.这与嵌套事务没有任何关系,就其本身而言,它是因为Python异常冒泡而发生的.外部挡路将由异常退出,这总是会导致回滚.这是正确的,不管最初是什么原因导致了异常.

不明显的情况是Z引发异常时会发生什么,这就是为什么文档需要特别注意的原因.作为referencedXY都将回滚:

当内部块成功完成时,如果稍后在外部块中引发异常,其效果仍然可以回滚.

现在,还可以捕获嵌套操作引发的异常.

with transaction.atomic():
    X
    try:
        with transaction.atomic():
            Y
    except IntgrityError:
        pass
    Z

在这种情况下,如果Y抛出异常,内部块将回滚(因为它带着异常退出),但外部块不会回滚(因为它没有).

这与您提到的两个答案中的任何一个中的信息都不矛盾,因为这两个答案都解决了不涉及捕获任何异常的特定问题(带有代码示例).

无论如何,感谢您的反馈,并有机会给出更全面的答案.

Django相关问答推荐

对象Django API中的对象

为什么Docker compose没有这样的文件或目录?

Django Prefetch上的多重过滤

只从查询集中获取某种类型的最新项目

有什么方法可以自动设置 Debug True Django application

Django 关系嵌套related_name

如何在 Django 模板视图中显示我的数据?

在 Django 的 TextField 中禁用 HTML 转义

模板过滤器修剪任何前导leading或尾随trailing空格

如何在 django 中生成 url

Django删除查询集的最后五个以外的所有内容

Django Admin - 覆盖自定义表单字段的小部件

base.html 中的 Django 变量

Django -- User.DoesNotExist 不存在?

这是验证 Django 模型字段的方法吗?

Django - 来自 QuerySet 的唯一列表

如何在 django 中仅获取表的特定列?

过滤查询参数

关闭 Django Rest Framework ModelViewSet 的自动分页

在 Python 中生成 API KEY 和 SECRET 的最简单和最安全的方法是什么