微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – Django嵌套事务 – “with transaction.atomic()” – 寻求澄清

Django nested transactions – “with transaction.atomic()”问题是,鉴于此……
def functionA():
    with transaction.atomic():
        #save something
        functionB()

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

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

凯文克里斯托弗亨利回答说:“是的,如果任何一个功能发生异常,他们都会回滚.”然后他引用the docs,其中说:

atomic blocks can be nested. In this case,when an inner block completes successfully,its effects can still be rolled back if an exception is raised in the outer block at a later point.

此文档引用似乎没有解决原始问题.文档说当INNER BLOCK(函数B)成功完成时,如果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()

……接着是这篇评论……

In this example,even if generate_relationships() causes a database error by breaking an integrity constraint,you can execute queries in add_children(),and the changes from create_parent() are still there.

如果我正确地阅读了doc,那就是对generate_relationships()的调用(类似于对原始问题中对functionB的调用)可能会失败并且create_parent()和add_children()中的更改将被提交到数据库.这似乎与Kevin Christopher Henry的回答相矛盾.

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

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

解决方法

这是一些具有嵌套事务块和数据库操作X,Y和Z的伪代码
with transaction.atomic():
    X
    with transaction.atomic():
        Y
    Z

如果X引发异常,那么显然没有任何操作会有机会在第一时间提交.

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

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

When an inner block completes successfully,its effects can still be rolled back if an exception is raised in the outer block at a later point.

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

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

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

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

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

原文地址:https://www.jb51.cc/mssql/78727.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐