Django嵌套事务 - "与transaction.atomic()" - 寻求澄清

mel*_*bit 14 sql django transactions

Django嵌套事务中 - "with transaction.atomic()"问题是,鉴于此......

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

def functionB():
    with transaction.atomic():
        #save another thing
Run Code Online (Sandbox Code Playgroud)

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

凯文克里斯托弗亨利回答说:"是的,如果在任何一个功能中发生异常,它们都将被回滚." 然后他引用了文档,其中说明:

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

此文档引用似乎没有解决原始问题.文档说当INNER BLOCK(是functionB)成功完成时,如果OUTER块(函数A)引发异常,它的效果仍然可以回滚.但问题是相反的情况.问题是,如果INNER块(functionB)FAILS是OUTER块(functionA)回滚?该文档引用未涉及该场景.

但是,在doc中我们看到这个例子......

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()
Run Code Online (Sandbox Code Playgroud)

......接着是这篇评论......

在此示例中,即使generate_relationships()通过破坏完整性约束导致数据库错误,您也可以执行查询add_children(),并且create_parent()仍然存在更改.

如果我在看文档正确它说调用generate_relationships()(这类似于调用functionB在原来的问题)可能会失败,并在所做的更改create_parent(),并add_children()会被提交到数据库.这似乎与Kevin Christopher Henry的回答相矛盾.

让我感到困惑的是,我在Django嵌套的Transaction.atomic中看到了相同的问题/答案.

我是Django和stackoverflow的新手,所以我对我阅读文档没有太多信心,但它似乎与这两种反应都相矛盾.我正在寻找更有经验的人的澄清.非常感谢.

Kev*_*nry 20

下面是一些伪代码嵌套事务块和数据库操作X,Y以及Z:

with transaction.atomic():
    X
    with transaction.atomic():
        Y
    Z
Run Code Online (Sandbox Code Playgroud)

如果X引发异常,那么显然没有任何操作会首先获得提交的机会.

如果Y引发异常 - 这是您引用的问题 - 那么外部块也将回滚.这与嵌套事务没有任何关系,本身就是因为Python异常冒泡而发生.外部块将由异常退出,该异常总是导致回滚.无论最初导致异常的原因是什么都是如此.

不明显的情况是在Z引发异常时会发生什么,这就是为什么文档要求它特别注意的原因.作为参照,二者XY将回滚:

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

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

with transaction.atomic():
    X
    try:
        with transaction.atomic():
            Y
    except IntgrityError:
        pass
    Z
Run Code Online (Sandbox Code Playgroud)

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

这与您提到的两个答案中的任何一个中的信息都不矛盾,因为那些答案解决了特定问题(使用代码示例),这些问题不涉及任何例外情况.

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

  • 好的!捕获的异常是我在文档中忽略的关键。我现在明白了。感谢您的澄清! (2认同)